Следующий код работает как положено. Исходный код, файл «file.txt» и «out.txt» кодируются с помощью utf8. Но это не работает, когда я меняю wchar_t
в char16_t
на первой строке main()
, Я пробовал и gcc5.4 и clang8.0 с -std=c++11
, Моя цель — заменить wchar_t
с char16_t
, как wchar_t
занимает в ОЗУ два места Я думал, что эти 2 типа одинаково хорошо поддерживаются в стандартах c ++ 11 и более поздних. Что мне здесь не хватает?
#include<iostream>
#include<fstream>
#include<locale>
#include<codecvt>
#include<string>
int main(){
typedef wchar_t my_char;
std::locale::global(std::locale("en_US.UTF-8"));
std::ofstream out("file.txt");
out << "123正则表达式abc" << std::endl;
out.close();
std::basic_ifstream<my_char> win("file.txt");
std::basic_string<my_char> wstr;
win >> wstr;
win.close();
std::ifstream in("file.txt");
std::string str;
in >> str;
in.close();
std::wstring_convert<std::codecvt_utf8<my_char>, my_char> my_char_conv;
std::basic_string<my_char> conv = my_char_conv.from_bytes(str);
std::cout << (wstr == conv ? "true" : "false") << std::endl;
std::basic_ofstream<my_char> wout("out.txt");
wout << wstr << std::endl << conv << std::endl;
wout.close();
return 0;
}
Измененный код не компилируется с clang8.0. Он компилируется с gcc5.4, но вылетает во время выполнения, как показано @Brian.
Различные классы потока нуждаются в наборе определений для работы. Стандартная библиотека требует соответствующих определений и объектов только для char
а также wchar_t
но не для char16_t
или же char32_t
, Вне моей головы необходимо следующее std::basic_ifstream<cT>
или же std::basic_ofstream<cT>
:
std::char_traits<cT>
указать, как ведет себя тип символа. я считать этот шаблон специализирован для char16_t
а также char32_t
,std::locale
должен содержать экземпляр std::num_put<cT>
фасет для форматирования числовых типов. Этот аспект может быть просто создан и новый std::locale
содержащий его может быть создан, но стандарт не требует, чтобы он присутствовал в std::locale
объект.std::locale
должен содержать экземпляр аспекта std::num_get<cT>
читать числовые типы. Опять же, этот аспект может быть создан, но не обязательно должен присутствовать по умолчанию.std::numpunct<cT>
должен быть специализированным и помещенным в использованный std::locale
иметь дело с десятичными точками, тысячами разделителей и текстовыми логическими значениями. Даже если он на самом деле не используется, на него будут ссылаться функции числового форматирования и синтаксического анализа. Там нет готовой специализации для char16_t
или же char32_t
,std::ctype<cT>
должен быть специализирован и помещен в используемый фасет для поддержки расширения, сужения и классификации типов символов. Там нет готовой специализации для char16_t
или же char32_t
,
std::codecvt<cT, char, std::mbstate_t>
должен быть специализированным и помещенным в использованный std::locale
преобразовывать между внешними байтовыми последовательностями и внутренними «символьными» последовательностями. Там нет готовой специализации для char16_t
или же char32_t
,Большинство аспектов довольно просто выполнить: им просто нужно переслать простое преобразование или выполнить поиск по таблице. Тем не менее std::codecvt
Фасет, как правило, довольно сложно, особенно потому, что std::mbstate_t
является непрозрачным типом с точки зрения стандартной библиотеки C ++.
Все это можно сделать. Прошло много времени с тех пор, как я в последний раз доказывал реализацию концепции для символьного типа. Это заняло у меня около одного дня работы. Конечно, я знал, что мне нужно делать, когда приступил к работе, реализовав ранее библиотеку locales и IOStreams. Добавление разумного количества тестов, а не просто демонстрация, вероятно, заняло бы у меня неделю или около того (при условии, что я действительно смогу сосредоточиться на этой работе).
Других решений пока нет …