C ++ 20 с u8, char8_t и std :: string - PullRequest
       40

C ++ 20 с u8, char8_t и std :: string

19 голосов
/ 01 июля 2019

C ++ 11 принес нам префикс u8 для литералов UTF-8, и я подумал, что это было круто несколько лет назад, и наполнил мой код такими вещами:

std::string myString = u8"●";

Это все хорошои хорошо, но проблема возникает в C ++ 20, он, кажется, больше не компилируется, потому что u8 создает char8_t *, и это несовместимо с std :: string, которая просто использует char.

Должен ли я бытьсоздать новую строку utf8?Какой последовательный и правильный способ сделать это в мире C ++ 20, где у нас есть более явные типы, которые на самом деле не соответствуют стандартному std :: string?

Ответы [ 2 ]

13 голосов
/ 01 июля 2019

Должен ли я создавать новую строку utf8?

Нет, это уже там. P0482 предлагает не только char8_t, но и новую специализацию std::basic_string для char8_t типов символов с именем std::u8string. Так что это уже компилируется с clang и libc++ из транка:

const std::u8string str = u8"●";

Тот факт, что std::string конструкция из u8 -литеральных разрывов вызывает сожаление. Из предложения:

В этом предложении не указаны какие-либо функции обратной совместимости, кроме сохранения интерфейсов, которые оно устарело. Отсутствие таких функций не связано с убеждением, что функции обратной совместимости не нужны. Автор считает, что такие функции необходимы, но временные ограничения не позволили адекватно исследовать, какие проблемы необходимо решать, в какой степени они должны решаться и как эти функции должны быть указаны. [...]

Но я полагаю, что большая часть такой инициализации, как указано выше, должна быть grep -подключаемой или подвергаться некоторым автоматическим clang исправлениям инструментов.

12 голосов
/ 01 июля 2019

В дополнение к ответу @ lubgr в статье char8_t исправление обратной совместимости (P1423) обсуждается несколько способов создания std::string с char8_t массивами символов.

По сути, идея заключается в том, что вы можете преобразовать массив u8 char в "обычный" массив символов, чтобы получить то же поведение, что и в C ++ 17, и раньше вам просто нужно быть немного более явным. В статье рассматриваются различные способы сделать это.

Самый простой (но не полностью нулевой, если вы не добавляете больше перегрузок) метод, который подходит вашему сценарию использования, является, вероятно, последним, т. Е. Вводите явные функции преобразования:

std::string from_u8string(const std::string &s) {
  return s;
}
std::string from_u8string(std::string &&s) {
  return std::move(s);
}
#if defined(__cpp_lib_char8_t)
std::string from_u8string(const std::u8string &s) {
  return std::string(s.begin(), s.end());
}
#endif
...