c++utf-8stdstringstreamsetlocale

std::stringstream gets broken after setting UTF8 locale


I'm having trouble with outputting numbers once I set a global locale in my C++ app. Here's a working code sample:

#include <locale>
#include <clocale>
#include <sstream>
#include <iostream>

void initLocale() {
    constexpr char locale_name[] = "en_US.UTF-8";
    std::setlocale( LC_ALL, locale_name );
    std::locale::global(std::locale(locale_name));
}

int main() {
    int64_t i = -123434534536;
    std::stringstream s1;
    s1 << i << "\n";
    std::cout << "Before locale: " << s1.str();
    
    initLocale();
    
    std::stringstream s2;
    s2 << i << "\n";
    std::cout << "After locale: " << s2.str();
    
    return 0;
}

I compile this code on LINUX (debian) with g++ using this command:

g++ -std=c++17 -o test test.cpp

The output I get by running the program is this:

Before locale: -123434534536
After locale: -123,434,534,536

Why does std::stringstream behave like this after setting the locale and how can I fix it?

P.S.: I need to use this locale in order to correctly handle non-ANSI characters in filenames (I have some files that contain Chinese characters)


Solution

  • libstdc++ always implemented locales this way, and I also found this to be annoying.

    The simplest solution is to explicitly imbue the "C" locale when formatting numeric values:

    std::stringstream s2;
    
    s2.imbue(std::locale{"C"});
    s2 << i << "\n";
    

    Depending on what actual formatting output operations are needed you may find it necessary to wall off all formatted integer output into their own std::ostream with an imbued "C" locale, and everything else gets formatted using the global locale.