最终,Boost文档对我的问题做出了很好的回答,但你需要阅读一些内容,并且最好比我发帖时更好地理解
std::locale
。
与
std
很好地协作
std::locale
是
facet
集合。标准定义了每个区域设置必须提供的一组facets,但除此之外,大多数都由实现决定。这包括区域设置行为和区域设置名称。
Boost::locale提供了一堆facets,收集到locales中,无论平台如何都会表现出相同的行为(至少如果您使用默认的ICU后端)。
boost::locale
提供了一组标准化的 std::locale,可以在各种平台上保持一致的行为,为广泛的文化规范提供完整的 Unicode 支持,并具有一致的命名。在使用非 boost 的
std::locale
(即由实现提供的区域设置)和
boost::locale
之间切换很容易,因为它们是相同类型 - 都是
std::facets
的集合,尽管实现不同。
boost::locale
很可能更好地完成您想要的任务。
通过
ICU,
boost::locale
进一步提供了访问完整 Unicode 支持的方式,这使您可以获得 ICU 的好处,而无需使用 ICU 的界面(不符合 C++ 规范)。
这是一个优势,因为任何 Unicode 的标准支持很可能通过区域设置框架来实现,并且任何 Unicode 意识程序也很可能需要进行区域设置处理(例如排序)。
关于数字的更加合理的行为
最后,
boost::locale
解决了通常实现 std::locales 中可能被称为重大缺陷的问题——任何流格式化的数字都会受到区域设置的影响,而不管这是否是期望的。有关详细讨论,请参阅
boost documentation。
因此,如果您正在使用 ofstream 读取或写入文件,并将全局
locale
设置为您平台的德语 locale,则浮点数的小数部分将以逗号分隔。如果您正在读写 csv 文件,则可能会出现问题。如果您使用
boost::locale
作为全局 locale,则只有在明确告诉它要使用数字输入/输出的区域设置约定时才会发生这种情况。请注意,许多库在后台使用区域设置信息,包括 boost::lexical_cast。同样,std::to_string 也是如此。因此,请考虑以下示例:
std::locale::global(std::locale("de_DE"));
auto demo = [](const std::string& label)
{
std::cout.imbue(std::locale());
float f = 1234.567890;
std::cout << label << "\n";
std::cout << "\t streamed: " << f << "\n";
std::cout << "\t to_string: " << std::to_string(f) << "\n";
};
std::locale::global(std::locale("C"));
demo("c locale");
std::locale::global(std::locale("de_DE"));
demo("std de locale");
boost::locale::generator gen;
std::locale::global(gen("de_DE.UTF-8"));
demo("boost de locale");
给出以下输出:
c locale
streamed: 1234.57
to_string: 1234.567871
std de locale
streamed: 1.234,57
to_string: 1234,567871
boost de locale
streamed: 1234.57
to_string: 1234,567871
在既实现人类交流(输出到GUI或终端)又实现机器间通信(CSV文件、XML等)的代码中,这种行为可能是不希望出现的。使用boost locale时,您可以明确指定何时需要地域格式,例如:
cout << boost::locale::as::currency << 123.45 << "\n";
cout << boost::locale::as::number << 12345.666 << "\n"
结论
看起来,应该优先使用boost::locale而不是系统提供的本地化。