如何使用 <codecvt> 转换 std::u16string -> std::wstring?

how does one convert std::u16string -> std::wstring using <codecvt>?

我发现了一堆关于类似主题的问题,但没有关于使用 <codecvt> 进行宽到宽转换的问题,这应该是现代代码中的正确选择。

std::codecvt_utf16<wchar_t> 似乎是执行转换的合乎逻辑的选择。

然而,std::wstring_convert 似乎期望 std::string 一方面。方法 from_bytesto_bytes 强调了这个目的。

我的意思是,到目前为止最好的解决方案是 std::copy,它可能适用于我的具体情况,但似乎技术含量低,而且可能也不太正确。

我有一种强烈的感觉,我遗漏了一些相当明显的东西。

干杯。

std::wstring_convertstd::codecvt... 类 在 C++17 及更高版本中已弃用。不再有在各种字符串 类.

之间进行转换的标准方法

如果你的编译器仍然支持类,你当然可以使用它们。但是,您不能使用它们将 直接 std::u16string 转换为 std::wstring(反之亦然)。您必须先转换为中间 UTF-8 std::string,然后再转换,例如:

std::u16string utf16 = ...;

std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> utf16conv;
std::string utf8 = utf16conv.to_bytes(utf16);

std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wconv;
std::wstring wstr = wconv.from_bytes(utf8);

只知道当 类 最终从标准库中删除时,这种方法 中断。

使用 std::copy()(或简单地使用各种 std::wstring 数据 construct/assign 方法)仅适用于 Windows,其中 wchar_tchar16_t 都是 16 位大小,表示 UTF-16:

std::u16string utf16 = ...;
std::wstring wstr;

#ifdef _WIN32
wstr.reserve(utf16.size());
std::copy(utf16.begin(), utf16.end(), std::back_inserter(wstr));
/*
or: wstr = std::wstring(utf16.begin(), utf16.end());
or: wstr.assign(utf16.begin(), utf16.end());
or: wstr = std::wstring(reinterpret_cast<const wchar_t*>(utf16.c_str()), utf16.size());
or: wstr.assign(reinterpret_cast<const wchar_t*>(utf16.c_str()), utf16.size());
*/
#else
// do something else ...
#endif

但是,在其他平台上,wchar_t 是表示 UTF-32 的 32 位大小,您需要使用上面显示的代码或 platform-specific 实际转换数据API 或可以进行数据转换的第 3 方 Unicode 库,例如 libiconvICU。等等