boost::locale和std::locale之间的权衡是什么?
What are the tradeoffs between boost::locale and std::locale?
我正在国际化一个大型c++遗留代码库的过程中,我面临着一个困难的决定:我应该使用boost::locale还是std c++ locale ?
我承诺使用utf-8。我们必须进行相当广泛的文本处理,尽管这不是我们代码的核心,但它很重要。我们可以期望完成大多数可能需要做的事情:时间、日期、数字和货币格式化、排序、regexp、子字符串隔离、与boost::文件系统的交互、DB访问等。
boost::locale的介绍我得到了
- 设置全局语言环境有副作用(以csv为例)。它影响printf和boolst lexical_cast。一些第三方库可能会崩溃。
- 数字格式在某些地区被破坏。
- 语言环境名称没有标准化。
- 许多供应商只提供C和POSIX,所以GCC只支持Linux下的本地化。
我很难评估第1点的影响,我想第2点如果影响到我们的话是相当严重的,而第3点和第4点对我们来说不会有什么大不了的。
社区是否一致认为Boost::locale是更好的选择?在标准社区中是否有任何行动来解决std::locale的问题?有人能帮我做个更明智的决定吗?
也许最重要的是,从一个迁移到另一个是否简单?这两家公司相互配合得如何?使用boost语言环境设置全局语言环境,然后使用std工具是否合法?
最后,boost文档很好地回答了我的问题,但是您必须做一些阅读,它有助于比我在发布时更好地理解std::locale
。
与std
配合得很好A std::locale
是facet
s的集合。该标准定义了每个语言环境必须提供的一组方面,但除此之外,似乎大部分都留给了实现。这包括区域设置行为,以及区域设置的名称。
boost::locale所做的是提供一堆facet,收集到locale中,无论平台如何(至少如果您使用默认的ICU后端),它们的行为都是相同的。
因此boost::locale
提供了一组标准化的std::locale,这些std::locale可以在不同平台上保持一致的行为,为广泛的文化规范提供完整的Unicode支持,并具有一致的命名。在使用非boost std::locale
(即提供语言环境的实现)和boost::locale
之间切换是微不足道的,因为它们是相同的类型—两者都是std::facets
的集合,尽管实现不同。机会是boost::locale
做你想做的事情做得更好。
完整的Unicode支持,适用于所有平台上的所有编码
此外,boost::locale
提供了一种通过ICU访问完整unicode支持的方法,这使您可以获得ICU的好处,而无需ICU的糟糕(不像c++)接口。
这是有利的,因为对Unicode的任何标准支持都很可能通过区域设置框架来实现,并且任何支持Unicode的程序也可能需要支持区域设置(例如,用于排序)。
对数字更理智的行为最后,boost::locale
解决了std::locale通常实现中的一个重大缺陷——任何流格式化的数字都会受到locale的影响,不管这是否可取——参见boost文档以获得详细讨论。
因此,如果您正在使用ofstream来读写文件,并且您已经将全局变量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等)的代码中,这可能是不受欢迎的行为。当使用boost语言环境时,您需要显式指定何时需要语言环境格式化,ala:
cout << boost::locale::as::currency << 123.45 << "n";
cout << boost::locale::as::number << 12345.666 << "n"
结论看起来boost::locale应该优先于系统提供的区域设置。
Locale基于std:: Locale框架,但以更语言正确的方式提供了更多选项。
如果你想在windows/MSVC上使用utf-8, std::locale是不允许的
- 传递 lambda 函数的权衡是什么?
- 与 boost::locale 关于"ß"大写的例外行为混淆
- 使用 std::locale 格式化法语数字时无效的 UTF-8 数据
- C++ std::locale( "en" ) 在 iOS 上引发异常
- 为什么 boost::locale::to_title 不返回预期的输出?
- sf::Windows上的音乐:api-ms-win-crt-locale-l1-1-0.dll:无法打开共享对象文件
- 为什么 std::locale( " " ).name() 在 clang 和 gcc 上给出不同的结果?
- std::locale 向"en_US.UTF-8"区域设置抛出runtime_error异常
- 为什么当我将 std::locale 设置为 "zh_CN.UTF-8" 时 std::istringstream 失败?
- Unicode 字符分类与 boost::locale
- 代码不会发送我想要的权衡
- 1/sqrt(x) 和 std::exp(-0.5 * std::log(x)) 之间的数值权衡
- C++11:std::locale::empty() 甚至是一个东西
- 如何为android构建boost::locale
- std::locale 导致 Helgrind 出错
- STD :: LOCALE与LCONV :: P_CS_PRECEDES没有等效
- 对 boost::locale:conv::between 的未定义引用
- std::locale/std::facet关键部分
- std::locale::global是否影响printf()函数
- boost::locale和std::locale之间的权衡是什么?