最后,boost 文档很好地回答了我的问题,但您必须阅读一些内容,这有助于比我在发布时更好地理解 std::locale。
与标准配合得很好
std::locale 是 facets 的集合。该标准定义了每个语言环境必须提供的一组方面,但除此之外,似乎大部分都留给了实现。这包括语言环境行为和语言环境的名称。
boost::locale 所做的是提供一堆方面,收集到语言环境中,无论平台如何,它们的行为方式都相同(至少如果您使用默认的 ICU 后端)。
所以boost::locale 提供了一组标准化的 std::locale,它们可以跨平台一致地运行,为广泛的文化规范提供完整的 Unicode 支持,并具有一致的命名。在使用非提升 std::locale(即实现提供的语言环境)和 boost::locale 之间切换是微不足道的,因为它们是相同的类型 - 两者都是 std::facets 的集合,尽管实现不同。 boost::locales 可能会更好地做你想做的事。
完整的 Unicode 支持,适用于所有平台上的所有编码
此外,boost::locale 提供了一种通过ICU 访问完整的 unicode 支持的方法,这使您能够获得 ICU 的好处,而无需 ICU 的糟糕(不是 C++ish)接口。
这是有利的,因为对 Unicode 的任何标准支持都很可能通过语言环境框架来实现,并且任何支持 Unicode 的程序也可能需要支持语言环境(例如排序规则)。
关于数字的更理智的行为
最后,boost::locale 解决了在 std::locales 的通常实现中可以合法地称为重大缺陷的问题——任何流格式的数字都将受到语言环境的影响,无论这是否可取——请参阅boost documentation for详细讨论。
因此,如果您使用 ofstream 来读取或写入文件,并且您已将 globale locale 设置为您平台的德语语言环境,您将使用逗号分隔浮点数的小数部分。如果您正在读取/写入 csv 文件,那可能是个问题。如果您使用 boost::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()); // imbue cout with the global 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"));//default.
demo("c locale");
std::locale::global(std::locale("de_DE"));//default.
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 等)的代码中,这可能是不受欢迎的行为。使用提升语言环境时,您明确指定何时需要语言环境格式,ala:
cout << boost::locale::as::currency << 123.45 << "\n";
cout << boost::locale::as::number << 12345.666 << "\n"
结论
似乎 boost::locale 应该优于系统提供的语言环境。