Since you use your test on a Linux system, the source code is UTF-8, so x and y are the same thing. These bytes are shunted, not modified, to the standard output std::cout << x and std::cout << y , and when you look at a web page (or when you look at the Linux terminal), you see a symbol as you expected.
std::wcout << z will be printed if you do two things:
std::ios::sync_with_stdio(false); std::wcout.imbue(std::locale("en_US.utf8"));
without unsynching from C, GNU libstdC ++ goes through C IO streams that can never print a wide char after printing a narrow char in the same stream. LLVM lib ++ even works with synchronization, but, of course, it still needs to tell the stream how to convert the wide characters to the bytes it sends to standard output.
To print b and a , you have to convert them to wide or narrow; even with wbuffer_convert configuring the stream, char32_t is very much. It will look like this:
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv32; std::cout << conv32.to_bytes(a) << '\n';
Putting it all together: http://coliru.stacked-crooked.com/a/a809c38e21cc1743
source share