Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wchar_t output with libc++

#include <locale>
#include <iostream>

int main()
{
    std::locale::global(std::locale("en_US.utf8"));
    std::wcout << L"Həł£ō שøяļđ\n";
    return 0;
}

This works as expected with libstdc++ (both gcc and clang), but only prints the first character (which happens to be ASCII) with libc++. I'm using libcxx-0.0_p20140322 on Gentoo Linux.

Is this a known bug in libc++, or just me not knowing how to cook it?

Update 1. I have tried

std::locale::global(std::locale("en_US.utf8"));
std::locale::global(std::locale(""));
std::setlocale(LC_ALL, "en_US.utf8");
std::setlocale(LC_ALL, "");

which all do the same thing.

Update 2. The wide string literal is here for simplicity. The same thing happens when the string is obtained in any other way (converted from UTF-8, read from binary file, ...)

like image 807
n. 1.8e9-where's-my-share m. Avatar asked Jul 03 '14 22:07

n. 1.8e9-where's-my-share m.


1 Answers

You have to explicitly imbue the output stream with a locale, like so:

std::wcout.imbue(std::locale());

This makes things work as expected. In fact, it is required by the standard:

27.5.3.3 ios_base functions

locale getloc() const;

4 If no locale has been imbued, a copy of the global C++ locale, locale(), in effect at the time of construction.

So when wcout is constructed, it gets a copy of the initial locale imbued in it. The initial locale is "C". My incorrect assumption was that streams which have no locale explicitly imbued use the current global locale always (and not just at the time of construction). This assumption is totally unreasonable if one thinks about it a little.

June 2021 edit: So in theory just imbue should work, however in practice it doesn't in libstdc++. One needs to set the global locale for this to work, which is probably a libstdc++ bug. Imbuing works with other wide-character streams, but not with std::wcout.

like image 86
n. 1.8e9-where's-my-share m. Avatar answered Nov 11 '22 19:11

n. 1.8e9-where's-my-share m.