Преобразование из wstring в u16string и обратно (стандартное соответствие) в C++17/C++20

Моя основная платформа — Windows, поэтому я использую внутреннюю кодировку UTF-16 (в основном строки BMP). Я хотел бы использовать вывод консоли для этих строк.

К сожалению, нет std::u16cout или std::u8cout, поэтому мне нужно использовать std::wcout. Поэтому я должен преобразовать свои u16strings в wstrings — как лучше (и проще всего) это сделать?

В Windows я знаю, что wstring указывает на данные UTF16, поэтому я могу создать простой std::u16string_view, который использует те же данные (без преобразования). Но в Linux wstring обычно UTF32... Есть ли способ сделать это без макросов и без таких вещей, как предположение sizeof(wchar_t) == 2 => utf16?


person Bernd    schedule 20.04.2020    source источник
comment
Если у вас не Windows, разве вы не должны использовать std::cout и std::string, а не std::wcout и std::wstring? То есть, не должно ли преобразование быть в UTF-8, которое повсеместно распространено на платформах, отличных от Windows?   -  person Nicol Bolas    schedule 20.04.2020
comment
Вероятно, он манипулирует данными, сгенерированными приложениями Windows и сгенерированными для приложений Windows на сервере Linux или чем-то в этом роде. edit: ах, он работает со строками BMP. Вот твоя причина   -  person user120242    schedule 20.04.2020
comment
Отвечает ли это на ваш вопрос? как преобразовать wstring в u16string?   -  person Luke    schedule 20.04.2020


Ответы (1)


В стандарте С++ 20 нет ничего, что преобразовывало бы wchar_t в char32_t и обратно. В конце концов, wchar_t должен быть достаточно большим, чтобы содержать любая поддерживаемая кодовая точка.

И действительно везде поддерживается Unicode выше U+FFFF, wchar_t 32-битный, кроме Windows (и в Java, но это не имеет значения). Так что да, даже сегодня переносимая работа с Unicode проблематична, и sizeof(wchar_t)==2 или #ifdef _WIN32 звучат как законные обходные пути.

Сказав это, wcout по-прежнему без проблем работает с wchar_t на всех платформах, независимо от базовой кодировки.

Только если вы сокращаете wstrings или работаете с отдельными кодовыми точками, и хотите поддерживать кодовые точки за пределами базовой плоскости, тогда вам необходимо примите во внимание суррогатные пары (что все еще довольно просто, 0xD800–0xDBFF = первая пара, 0xDC00–0xDFFF = вторая пара, не разрезайте их).

person rustyx    schedule 20.04.2020
comment
Я думаю, также важно отметить, что char32_t представляет собой только кодовую точку, а не графему. Если вам нужно работать с реальными визуализированными графемами, для которых требуется специализированная библиотека. Это сложно... немного. - person Mgetz; 20.04.2020
comment
Да, в Unicode тоже есть c̮oͣm̥bͮi̪n̆ìnͨǵ chh̎a͏r̷a͍c̘t́er̗sͥ… - person rustyx; 20.04.2020
comment
Я сделал это сейчас с вашим обходным путем... Нехорошо, но работает :-) - person Bernd; 15.07.2020