Compiling and running the following code on my machine (MacOS 10.14.x) results in printing an empty string on clang++ and throws a runtime error on g++. Why?
#include <locale>
#include <iostream>
int main()
{
std::cout << "User-preferred locale setting is " <<
std::locale("").name().c_str() << '\n';
return 0;
}
$ clang++ locale.cc
$ ./a.out
User-preferred locale setting is
$ g++-mp-8 locale.cc
$ ./a.out
terminate called after throwing an instance of 'std::runtime_error'
what(): locale::facet::_S_create_c_locale name not valid
User-preferred locale setting is Abort trap: 6
$ clang++ --version
clang version 7.0.1 (tags/RELEASE_701/final)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /opt/local/libexec/llvm-7.0/bin
$ g++-mp-8 --version
g++-mp-8 (MacPorts gcc8 8.3.0_0) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
At this time, I don't think it is a MacOS issue as running the example on cppreference.com also yields different results.
You can try it yourself for different compiler versions at: https://en.cppreference.com/w/cpp/locale/locale/name
In any case, it doesn't report the same as:
#include <locale>
#include <iostream>
#include <string>
int main()
{
std::cout << "User-preferred locale setting is "
<< setlocale(LC_ALL, "") << "\n";
return 0;
}
Which returns the same result ("en_US.UTF-8") for both compilers.
What am I missing?
You are right "The set of valid string argument values is "C", "", and any implementation-defined values..." But if you try to set to an unknown local (that may be returned by the local("")) it will throw a run-time error.
Take a look at the source code of libstdc++-v3/config/locale/gnu/c_locale.cc
locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s, __c_locale __old)
{
__cloc = __newlocale(1 << LC_ALL, __s, __old);
if (!__cloc)
{
// This named locale is not supported by the underlying OS.
__throw_runtime_error(__N("locale::facet::_S_create_c_locale name not valid"));
}
}
__newlocale
function is the one to blame. its a C function which will handle the conversion of the values passed to it.
on MAC-OS it seems that libstdc++
is not handling correctly the "" value and even does ton of problems with a lot of locales.
Its a well known issue in libstdc++ (which is used by g++). you can find it in multiple places easily, bug report 1,bug report 2, example 1. As you can see currently the libstdc++ supports only the "C" locales.
I say use ICU :)