Unicode в C++11


я немного читал по теме Unicode-в частности, UTF-8 - (не) поддержка в C++11, и я надеялся, что гуру на Stack Overflow могут убедить меня, что мое понимание правильно, или указать, где я неправильно понял или пропустил что-то, если это так.

краткий обзор

во-первых, хорошо: вы можете определить UTF-8, UTF-16 и UCS-4 литералов в исходном коде. Кроме того,<locale> заголовок содержит несколько std::codecvt реализации, которые могут конвертировать между любым из UTF-8, UTF-16, UCS-4 и многобайтовой кодировкой платформы (хотя API кажется, мягко говоря, менее чем простым). Эти codecvt реализации могут быть imbue() ' d на потоках, чтобы позволить вам сделать преобразование, как Вы читаете или пишете файл (или другой поток).

[EDIT: Cubbi указывает в комментариях, что я забыл упомянуть о , которая содержит std::codecvt реализации которых не зависит от локали. Кроме того,std::wstring_convert и wbuffer_convert функции могут использовать эти codecvtS для преобразования строк и буферов напрямую, не полагаясь на потоки.]

C++11 также включает в себя C99 / C11 <uchar.h> заголовок, который содержит функции для преобразования отдельных символов из многобайтовой кодировки платформы (которая может быть или не быть UTF-8) В и из UCS-2 и UCS-4.

однако, это о степени его. Хотя вы, конечно, можете хранить текст UTF-8 в std::string, там я не вижу способов сделать с ним что-то действительно полезное. Например, кроме определения литерала в коде, вы не можете проверить массив байтов как содержащий допустимый UTF-8, вы не можете узнать длину (т. е. количество символов Юникода, для некоторого определения "символа") UTF-8-containing std::string, и вы не можете перебирать std::string в любом случае, кроме байт за байтом.

аналогично, даже добавление C++11 std::u16string не поддерживает UTF-16, но только старый UCS-2 - он не поддерживает суррогатные пары, оставляя вас только с BMP.

замечания

учитывая, что UTF-8 является стандартным способом обработки Unicode практически на каждой Unix-производной системе (включая Mac OS X и* Linux) и в значительной степени стал де-факто стандартом в интернете, отсутствие поддержки в современном C++ кажется довольно серьезным упущением. Даже на Windows, тот факт, что новый std::u16string на самом деле не поддерживают UTF-16 кажется несколько прискорбным.

* как указано в комментариях и ясно здесь, BSD-производные части Mac OS используют UTF-8, в то время как Cocoa использует UTF-16.

вопросы

если вы сумели прочитать все это, спасибо! Просто несколько быстрых вопросов, так как это переполнение стека в конце концов...

  • является ли приведенный выше анализ правильным, или есть какие-либо другие средства поддержки Unicode, которые я не хватает?

  • комитет по стандартам проделал фантастическую работу за последние пару лет, продвигая C++ вперед быстрыми темпами. Они все умные люди, и я предполагаю, что они хорошо знают о вышеуказанных недостатках. Есть ли какая-то известная причина, по которой поддержка Unicode остается такой плохой в C++?

  • забегая вперед, кто-нибудь знает о каких-либо предложениях по исправлению ситуации? Быстрый поиск на isocpp.org не похоже, чтобы раскрыть что угодно.

EDIT: спасибо всем за ваши ответы. Я должен признаться, что нахожу их немного обескураживающими-похоже, статус-кво вряд ли изменится в ближайшем будущем. Если есть консенсус среди cognoscenti, похоже, что полная поддержка Unicode слишком сложна, и любое решение должно переопределить большую часть ICU, чтобы считаться полезным.

я лично с этим не согласен; Я думаю, что есть ценная середина, которую нужно найти. Например, алгоритмы проверки и нормализации для UTF-8 и UTF-16 хорошо определены консорциумом Unicode и могут быть предоставлены стандартной библиотекой в качестве свободных функций, скажем, a std::unicode пространство имен. Это само по себе было бы большим подспорьем для программ на C++, которые должны взаимодействовать с библиотеками, ожидающими ввода Unicode. Но исходя из приведенного ниже ответа (окрашенного, надо сказать, с оттенком горечи) кажется, что предложение щенка ибо именно такого рода ограниченная функциональность не была хорошо воспринята.

2 54

2 ответа:

является ли приведенный выше анализ правильным

давайте посмотрим.

вы не можете проверить массив байтов как содержащий допустимый UTF-8

неправильные. std::codecvt_utf8<char32_t>::length(start, end, max_lenght) возвращает количество байтов в массиве.

вы не можете узнать длину

частично правильно. Можно конвертировать в char32_t и узнать длину результата. Нет никакого легко способ узнать длина без фактического пересчета (см. ниже). Надо сказать, что потребность в подсчете символов (в любом смысле) возникает довольно нечасто.

вы не можете перебирать std:: string любым способом, кроме байт за байтом

неправильные. std::codecvt_utf8<char32_t>::length(start, end, 1) дает вам возможность перебирать "символы" UTF-8 (единицы кода Unicode) и, конечно же, определять их количество (это не "простой" способ подсчета количества символов, но это путь.)

на самом деле не поддерживает UTF-16

неправильные. Можно конвертировать в UTF-16 и из него, например,std::codecvt_utf8_utf16<char16_t>. Результатом преобразования в UTF-16 является, ну, UTF-16. Это не ограничивается BMP.

демо, которое иллюстрирует эти точки.

если я пропустил некоторые другие "вы не можете", пожалуйста, укажите на это, и я обращусь к нему.

важное дополнение. Эти объекты устаревший в C++17. Это, вероятно, означает, что они уйдут в какой-нибудь будущей версии C++. Используйте их на свой страх и риск. Все эти вещи, перечисленные в исходном вопросе, теперь нельзя (безопасно) сделать снова, используя только стандартную библиотеку.

является ли приведенный выше анализ правильным, или есть какие-либо другие Средства поддержки Unicode, которые мне не хватает?

Вам также не хватает полного отказа литералов UTF-8. У них нет отдельного типа для узкого символьные литералы, которые могут иметь совершенно несвязанные (например, кодировка) кодировка. Так что они не только не добавили никаких серьезных новых объектов в C++11, они сломали то немногое, что было, потому что теперь вы даже не можете предположить, что a char* в узкая строка-кодирование для вашей платформы, если UTF-8 не является узкой Строковой кодировкой. Так что новая функция здесь "мы полностью сломали char - основанные строки на каждой платформе, где UTF-8 не является существующей узкой Строковой кодировкой".

комитет по стандартам проделал фантастическую работу в последние пару лет годы двигают C++ вперед в быстром темпе. Они все умные люди и Я предполагаю, что они хорошо осведомлены о вышеперечисленных недостатках. Есть конкретной известной причины что поддержка Unicode остается настолько бедной C++?

комитет просто, кажется, не дает дерьмо о Unicode.

кроме того, многие алгоритмы поддержки Unicode - это просто алгоритмы. Это означает, что для того, чтобы предложить достойный интерфейс, нам нужны диапазоны. И мы все знаем, что комитет не может понять, чего они хотят от диапазонов w.r.t. Новая вещь Iterables от Эрика ниблера может иметь выстрел.

идя вперед, кто-нибудь знает о каких-либо предложения по исправлению ситуация? Быстрый поиск на isocpp.org не похоже, чтобы раскрыть что угодно.

был N3572, который я написал. Но когда я приехал в Бристоль и представил его, было много проблем.

во-вторых, получается выходит, что за него голосует тот, кто случайно забредет в то время. Это означает, что если ваша статья будет перенесена, у вас есть относительно случайная группа людей, которые могут или не могут ничего знать о предмете. Или действительно, все что угодно.

В-третьих, по какой-то причине они, похоже, не рассматривают текущую ситуацию как серьезную проблему. Вы можете получить бесконечное обсуждение о том, как именно optional<T> операции сравнения должны быть определены, но работа с пользователем вход? Кого это волнует?

В-четвертых, каждая бумага нуждается в чемпионе, эффективно, чтобы представить и поддерживать его. Учитывая предыдущие проблемы, плюс тот факт, что я не могу позволить себе ездить на другие встречи, это, конечно, не будет мной, не будет меня в будущем, если вы не хотите пожертвовать все мои дорожные расходы и платить зарплату сверху, и никто другой, казалось, не заботился достаточно, чтобы приложить усилия.