boost::locale和std::locale之间的权衡是什么?

What are the tradeoffs between boost::locale and std::locale?

本文关键字:locale 权衡 是什么 std boost 之间      更新时间:2023-10-16

我正在国际化一个大型c++遗留代码库的过程中,我面临着一个困难的决定:我应该使用boost::locale还是std c++ locale ?

我承诺使用utf-8。我们必须进行相当广泛的文本处理,尽管这不是我们代码的核心,但它很重要。我们可以期望完成大多数可能需要做的事情:时间、日期、数字和货币格式化、排序、regexp、子字符串隔离、与boost::文件系统的交互、DB访问等。

boost::locale的介绍我得到了

  1. 设置全局语言环境有副作用(以csv为例)。它影响printf和boolst lexical_cast。一些第三方库可能会崩溃。
  2. 数字格式在某些地区被破坏。
  3. 语言环境名称没有标准化。
  4. 许多供应商只提供C和POSIX,所以GCC只支持Linux下的本地化。

我很难评估第1点的影响,我想第2点如果影响到我们的话是相当严重的,而第3点和第4点对我们来说不会有什么大不了的。

社区是否一致认为Boost::locale是更好的选择?在标准社区中是否有任何行动来解决std::locale的问题?有人能帮我做个更明智的决定吗?

也许最重要的是,从一个迁移到另一个是否简单?这两家公司相互配合得如何?使用boost语言环境设置全局语言环境,然后使用std工具是否合法?

最后,boost文档很好地回答了我的问题,但是您必须做一些阅读,它有助于比我在发布时更好地理解std::locale

与std

配合得很好

A std::localefacet 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是不允许的