Visual Studio C++ 2015 std::codecvt 与 char16_t 或 char32_t
Visual Studio C++ 2015 std::codecvt with char16_t or char32_t
这段代码在VS2013下编译成功:
std::string Unicode::utf16_to_utf8(std::u16string utf16_string)
{
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
return convert.to_bytes(utf16_string);
}
现在使用 VS2015 我得到:
1>unicode.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: static class std::locale::id std::codecvt<char16_t,char,struct _Mbstatet>::id" (__imp_?id@?$codecvt@_SDU_Mbstatet@@@std@@2V0locale@2@A)
老问题,但供将来参考:这是 Visual Studio 2015 中的一个已知错误,如 MSDN Social this thread 中最新的 post(2016 年 1 月 7 日)所述.
您的示例的解决方法如下所示(为简单起见,我将您的方法实现为免费函数):
#include <codecvt>
#include <locale>
#include <string>
#include <iostream>
#if _MSC_VER >= 1900
std::string utf16_to_utf8(std::u16string utf16_string)
{
std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> convert;
auto p = reinterpret_cast<const int16_t *>(utf16_string.data());
return convert.to_bytes(p, p + utf16_string.size());
}
#else
std::string utf16_to_utf8(std::u16string utf16_string)
{
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
return convert.to_bytes(utf16_string);
}
#endif
int main()
{
std::cout << utf16_to_utf8(u"Élémentaire, mon cher Watson!") << std::endl;
return 0;
}
希望该问题将在未来的版本中得到解决,否则 #if
条件将需要改进。
更新:不,在 VS 2017 中未修复。因此,我已将预处理器条件更新为 >= 1900
(最初是 == 1900
)。
在 cpp 文件中定义缺失的符号。
// Apparently Microsoft forgot to define a symbol for codecvt.
// Works with /MT only
#include <locale>
#if (!_DLL) && (_MSC_VER >= 1900 /* VS 2015*/) && (_MSC_VER <= 1911 /* VS 2017 */)
std::locale::id std::codecvt<char16_t, char, _Mbstatet>::id;
#endif
另一种可能的解决方法是为 wstring_convert 使用默认的第二个模板参数 (wchar_t)。它适用于 "MS Visual Studio 2015 update 3"。请注意,它是非平台无关解决方案。仅 Windows。
std::string utf16_to_utf8(std::u16string u16_string)
{
std::wstring wide_string(u16_string.begin(), u16_string.end());
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
return convert.to_bytes(wide_string);
}
这在 VS2017 中对我有用:
std::wstring utf8_to_utf16(std::string utf8_string)
{
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>{}.from_bytes(utf8_string);
}
std::string utf16_to_utf8(std::wstring utf16_string)
{
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>{}.to_bytes(utf16_string);
}
这段代码在VS2013下编译成功:
std::string Unicode::utf16_to_utf8(std::u16string utf16_string)
{
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
return convert.to_bytes(utf16_string);
}
现在使用 VS2015 我得到:
1>unicode.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public: static class std::locale::id std::codecvt<char16_t,char,struct _Mbstatet>::id" (__imp_?id@?$codecvt@_SDU_Mbstatet@@@std@@2V0locale@2@A)
老问题,但供将来参考:这是 Visual Studio 2015 中的一个已知错误,如 MSDN Social this thread 中最新的 post(2016 年 1 月 7 日)所述.
您的示例的解决方法如下所示(为简单起见,我将您的方法实现为免费函数):
#include <codecvt>
#include <locale>
#include <string>
#include <iostream>
#if _MSC_VER >= 1900
std::string utf16_to_utf8(std::u16string utf16_string)
{
std::wstring_convert<std::codecvt_utf8_utf16<int16_t>, int16_t> convert;
auto p = reinterpret_cast<const int16_t *>(utf16_string.data());
return convert.to_bytes(p, p + utf16_string.size());
}
#else
std::string utf16_to_utf8(std::u16string utf16_string)
{
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
return convert.to_bytes(utf16_string);
}
#endif
int main()
{
std::cout << utf16_to_utf8(u"Élémentaire, mon cher Watson!") << std::endl;
return 0;
}
希望该问题将在未来的版本中得到解决,否则 #if
条件将需要改进。
更新:不,在 VS 2017 中未修复。因此,我已将预处理器条件更新为 >= 1900
(最初是 == 1900
)。
在 cpp 文件中定义缺失的符号。
// Apparently Microsoft forgot to define a symbol for codecvt.
// Works with /MT only
#include <locale>
#if (!_DLL) && (_MSC_VER >= 1900 /* VS 2015*/) && (_MSC_VER <= 1911 /* VS 2017 */)
std::locale::id std::codecvt<char16_t, char, _Mbstatet>::id;
#endif
另一种可能的解决方法是为 wstring_convert 使用默认的第二个模板参数 (wchar_t)。它适用于 "MS Visual Studio 2015 update 3"。请注意,它是非平台无关解决方案。仅 Windows。
std::string utf16_to_utf8(std::u16string u16_string)
{
std::wstring wide_string(u16_string.begin(), u16_string.end());
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
return convert.to_bytes(wide_string);
}
这在 VS2017 中对我有用:
std::wstring utf8_to_utf16(std::string utf8_string)
{
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>{}.from_bytes(utf8_string);
}
std::string utf16_to_utf8(std::wstring utf16_string)
{
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>{}.to_bytes(utf16_string);
}