Подтвердить что ты не робот

Visual Studio С++ 2015 std:: codecvt с char16_t или 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" ([email protected][email protected][email protected]@@[email protected]@[email protected]@A)
4b9b3361

Ответ 1

Старый вопрос, но для справки в будущем: это известная ошибка в Visual Studio 2015, как объясняется в последнем сообщении (7 января 2016 года) в этой теме 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;
}

Будем надеяться, что проблема будет исправлена ​​в будущих выпусках, иначе условие #if нуждается в уточнении. UPDATE: нет, не зафиксировано в VS 2017. Поэтому я обновил препроцессор условным до >= 1900 (изначально был == 1900).

Ответ 2

Определите недостающий символ в файле 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

Ответ 3

Другим возможным обходным решением является использование стандартного параметра второго шаблона (wchar_t) для wstring_convert. Он работает для обновления MS Visual Studio 2015 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);
}