C++ 为什么std::locale(";).name()在clang和gcc上给出不同的结果?
在我的机器(MacOS 10.14.x)上编译并运行以下代码会导致在clang++上打印空字符串,并在g++上引发运行时错误。为什么?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';
#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"));
}
}