Visual Studio C++ 2015 std :: codecvt with char16_t或char32_t

use*_*139 30 c++ stl char16-t char32-t visual-studio-2015

这段代码在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);
}
Run Code Online (Sandbox Code Playgroud)

现在使用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)
Run Code Online (Sandbox Code Playgroud)

JPN*_*gon 29

旧问题,但供将来参考:这是Visual Studio 2015中的已知错误,如最新帖子(2016年1月7日)在MSDN Social的这个主题中所述.

您的示例的解决方法如下所示(为简单起见,我将您的方法实现为免费函数):

#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;
}
Run Code Online (Sandbox Code Playgroud)

希望问题将在未来版本中得到修复,否则#if条件将需要改进.更新:nope,在VS 2017中没有修复.因此,我已经将预处理器条件更新为>= 1900(最初是== 1900).

  • 好吧,来自M $开发人员的这种方法令人沮丧......想象一下,你需要以这样的方式重写大量的代码...... (6认同)
  • 仍未修复VS 2019预览版. (3认同)
  • 那对我有用。反方向呢?如果我做一个 auto p = reinterpret_cast&lt;const char *&gt;(utf8_string.data()); 和 convert.from_bytes(p) 相反,我得到“没有合适的用户定义的转换,从“std::basic_string&lt;int16_t, std::char_traits&lt;int16_t&gt;, std::allocator&lt;int16_t&gt;&gt;”到“std:: u16string“存在” (2认同)

pas*_*alx 8

在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
Run Code Online (Sandbox Code Playgroud)

  • VS2017:错误C2491:'std :: codecvt &lt;char16_t,char,_Mbstatet&gt; :: id':dllimport静态数据成员的定义不允许 (2认同)
  • 实际上,它不能使用** / MD **进行编译,因为外部DLL无法知道/使用我们的定义。它确实适用于** / MT **。因此,这只是解决方法的一半:-) (2认同)

Pau*_*ams 5

This worked for me in 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);
}
Run Code Online (Sandbox Code Playgroud)