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

12

我正在国际化一个大型的C++老代码库,面临一个困难的决定:应该使用boost::locale还是std C++ locales?

我打算使用utf-8。我们需要进行相当广泛的文本处理,虽然这不是我们代码的核心,但它也很重要。我们可以预期需要做一些常见的操作:时间、日期、数字和货币格式化,排序、正则表达式、子字符串分离、与boost::filesystem、数据库访问等的交互。

介绍boost::locale,我知道:

  1. 设置全局语言环境会产生副作用(如CSV示例)。它会影响printf和boolst lexical_cast。有些第三方库可能会出问题。
  2. 在某些语言环境下,数字格式化会出错。
  3. 语言环境名称没有标准化。
  4. 许多供应商只提供C和POSIX,因此GCC仅在Linux下支持本地化。

我很难评估第1点的影响。如果第2点影响了我们,那么问题就相当严重,第3和第4点对我们来说并不是什么大问题。

社区中是否有共识认为boost::locale是更好的选择?标准委员会是否有任何动议来解决std::locale的问题?有人能帮我做出更明智的决定吗?

也许最重要的是,从一个选项迁移到另一个选项是否简单?这两个选项之间的兼容性如何?使用boost locale设置全局语言环境,然后使用std设施是否合法?


至少看起来,如果你使用boost,你需要自己设置std::locale:http://www.boost.org/doc/libs/1_58_0/libs/locale/doc/html/faq.html#faq_number - Buddy
2个回答

10
最终,Boost文档对我的问题做出了很好的回答,但你需要阅读一些内容,并且最好比我发帖时更好地理解std::locale
std很好地协作 std::localefacet集合。标准定义了每个区域设置必须提供的一组facets,但除此之外,大多数都由实现决定。这包括区域设置行为和区域设置名称。
Boost::locale提供了一堆facets,收集到locales中,无论平台如何都会表现出相同的行为(至少如果您使用默认的ICU后端)。 boost::locale 提供了一组标准化的 std::locale,可以在各种平台上保持一致的行为,为广泛的文化规范提供完整的 Unicode 支持,并具有一致的命名。在使用非 boost 的 std::locale(即由实现提供的区域设置)和 boost::locale 之间切换很容易,因为它们是相同类型 - 都是 std::facets 的集合,尽管实现不同。boost::locale 很可能更好地完成您想要的任务。
通过 ICUboost::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()); // 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 locale时,您可以明确指定何时需要地域格式,例如:
cout << boost::locale::as::currency << 123.45 << "\n";
cout << boost::locale::as::number << 12345.666 << "\n"

结论

看起来,应该优先使用boost::locale而不是系统提供的本地化。


3
Boost.Locale基于std::locale框架,但以更语言学正确的方式提供了更多选项。
如果您想在Windows/MSVC上使用utf-8,则std::locale无法胜任。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接