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
функции могут использовать эти codecvt
S для преобразования строк и буферов напрямую, не полагаясь на потоки.]
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 ответа:
является ли приведенный выше анализ правильным
давайте посмотрим.
вы не можете проверить массив байтов как содержащий допустимый 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>
операции сравнения должны быть определены, но работа с пользователем вход? Кого это волнует?В-четвертых, каждая бумага нуждается в чемпионе, эффективно, чтобы представить и поддерживать его. Учитывая предыдущие проблемы, плюс тот факт, что я не могу позволить себе ездить на другие встречи, это, конечно, не будет мной, не будет меня в будущем, если вы не хотите пожертвовать все мои дорожные расходы и платить зарплату сверху, и никто другой, казалось, не заботился достаточно, чтобы приложить усилия.