【问题标题】:Where to put std::wstring_convert<std::codecvt_utf8<wchar_t>>?在哪里放置 std::wstring_convert<std::codecvt_utf8<wchar_t>>?
【发布时间】:2017-03-11 18:41:38
【问题描述】:

我正在计划一个使用 C++Builder 10.1 (Clang 3.3) 的新 C++11 Win32/64 项目,并考虑在核心功能方面以最便携的方式实现它,所以我想将 UTF-8 用于 std::string 编码(另外,因为它是我打算使用的 SQLite C++ 包装器 SQLiteCpp 的默认编码)。

为了与 Win-API 交互,我决定使用 &lt;codecvt&gt;&lt;locale&gt;std::wstring_convert&lt;std::codecvt_utf8_utf16&lt;wchar_t&gt;&gt; 中的 .to_bytes().from_bytes() 函数。

所以,现在我想知道,放置转换器对象的最佳做法是什么。

我应该给它自己的单元和命名空间,例如

.h:

...
#include <codecvt>
#include <locale>

namespace cnv
{
    extern std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> wcu8;
}
...

.cpp:

...
namespace cnv
{
    std::wstring_convert<std::codecvt_utf8<wchar_t>> wcu8;
}
...

并将其包含在任何地方以便在需要的地方使用cnv::wcu8.to_bytes(xyz)

或者在我需要在编码之间转换的每个函数实现中创建一个实例更好?

【问题讨论】:

  • 如果您的唯一目的是 WIn32/64,为什么还需要它便携?如果是这样的话,你还不如忘记转换而只使用 wstring。
  • 它适用于Windows现在,将来可能会为其他系统编译。
  • 我对@9​​87654331@ 的体验是GCC 和clang 不太支持它。最值得注意的是 Travis CI 上的默认编译器在包含 codecvt 标头时会窒息。只是我的两分钱。

标签: c++ c++11 clang c++builder clang++


【解决方案1】:

我不会将std::wstring_convert 存储在全局变量中,因为这不是线程安全的,而且不会给你带来太多好处。每次需要时实例化 std::wstring_convert 可能会影响性能,但这不应该是您一开始的主要关注点(过早优化)。

所以我只是把那个东西包装成函数:

std::wstring utf8_to_wstr( const std::string& utf8 ) {
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> wcu8;
    return wcu8.from_bytes( utf8 );
}

std::string wstr_to_utf8( const std::wstring& utf16 ) {
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> wcu8;
    return wcu8.to_bytes( utf16 );
}

您必须在某处捕获std::range_error 异常。如果由于某种原因(无效的代码点等)转换失败,std::wstring_convert 会抛出它。

如果您稍后在字符串转换方面遇到性能瓶颈,您仍然可以在代码的关键点直接实例化 std::wstring_convert,例如。 G。在转换许多字符串的长时间运行循环之外。

【讨论】:

    猜你喜欢
    • 2011-09-22
    • 2013-10-21
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 2022-01-21
    • 2016-10-16
    相关资源
    最近更新 更多