C++ 为什么std::locale(";).name()在clang和gcc上给出不同的结果?

C++ 为什么std::locale(";).name()在clang和gcc上给出不同的结果?,c++,g++,locale,clang++,setlocale,C++,G++,Locale,Clang++,Setlocale,在我的机器(MacOS 10.14.x)上编译并运行以下代码会导致在clang++上打印空字符串,并在g++上引发运行时错误。为什么? #include <locale> #include <iostream> int main() { std::cout << "User-preferred locale setting is " << std::locale("").name().c_str() << '\n';

在我的机器(MacOS 10.14.x)上编译并运行以下代码会导致在clang++上打印空字符串,并在g++上引发运行时错误。为什么?

#include <locale>
#include <iostream>


int main()
{
  std::cout << "User-preferred locale setting is " <<
    std::locale("").name().c_str() << '\n';

  return 0;
}
目前,我认为这不是MacOS的问题,因为在cppreference.com上运行该示例也会产生不同的结果

您可以在以下位置针对不同的编译器版本进行尝试:

在任何情况下,它都不会报告与以下内容相同的内容:

#include <locale>
#include <iostream>
#include <string>

int main()
{
  std::cout << "User-preferred locale setting is "
            << setlocale(LC_ALL, "") << "\n";

  return 0;
}
#包括
#包括
#包括
int main()
{

std::cout差异可能来自这样一个事实,即clang++使用
libc++
,而g++使用
libstdc++
。函数
std::locale()
在这两个函数中都有定义,并且实现不同

您可以使用
strace
(如果可用)对此进行检查,如下所示:

$ strace -e file ./a.out
...
open("/usr/lib/.../libstdc++.so.6", O_RDONLY|O_CLOEXEC) = 3
...
在本例中,使用了
libstdc++

您是对的“有效字符串参数值集是”C“,”,以及任何实现定义的值…” 但是如果您试图设置为未知的本地(可能由本地(“”)返回),它将抛出运行时错误

请看一下
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"));
    }
}
locale::facet::_S_create_c_locale(uu c_locale&uu cloc,const char*u S,u c_locale u old)
{

__cloc=\uuuuNewLocale(1“在g++上引发运行时错误”还有其他信息吗?抛出std::runtime_错误。我编辑了该问题以添加MWE编译和结果。异常消息似乎非常具体:区域设置名称无效。文档说明,如果操作系统没有具有指定名称的区域设置(在本例中为空字符串),则构造函数可以抛出std::runtime_错误是否有理由使用空字符串而不是无参数构造函数?从C++标准“22.1.1.2区域构造函数和析构函数”中,“有效字符串参数值的集合是“C”、“”和任何实现定义的值。这与C一致,因为空字符串从环境中获取用户首选的本地变量(通常使用LANG或等效环境变量设置)。从我阅读的文档来看,无参数构造函数应该表示最近调用std::locale::global时设置的区域设置,这不是一回事。我为两个编译器都尝试了两个版本,效果都很好,没有错误,结果也一样,正如您在这里看到的:谢谢。我正在将问题标记为已回答。基本上我是在尝试为了理解为什么这两个编译器都不能支持“框外”的标准。在我的特定情况下,我只是尝试用C++来替代当前运行时区域名称,而不是设置为“代码< >设置区域(LCyALL,“”)< /C>。
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"));
    }
}