Все зависит от того, что вы подразумеваете под «иметь дело», но одно можно сказать наверняка: в том, что касается Unicode std::basic_string
вообще не предоставляет никакой реальной функциональности.
В любой конкретной программе,вам потребуется выполнить X операций с поддержкой Unicode, например, интеллектуальное сопоставление строк, сложение регистра, регулярное выражение, поиск разрывов слов, использование строки Unicode в качестве имени пути и т. д.
Поддержка этих операцийпочти всегда будет какая-то библиотека и / или собственный API, предоставляемый платформой, и цель для меня будет состоять в том, чтобы хранить и манипулировать моими строками таким образом, чтобы эти операции могли выполняться без разброса знаний о базовой библиотекеи поддержка нативного API во всем коде больше, чем необходимо.Я также хотел бы рассчитывать на будущее в отношении ширины символов, которые я храню в своих строках, на случай, если я передумаю.
Предположим, например, что вы решили использовать ICU делать тяжелую работу.Сразу же возникает очевидная проблема: icu::UnicodeString
никак не связан с std::basic_string
.Что делать?Работать исключительно с icu::UnicodeString
по всему коду?Возможно, нет.
Или, может быть, фокус приложения переключается с европейских языков на азиатские, так что UTF-16 становится (возможно) лучшим выбором, чем UTF-8.
Итак, мойможно было бы использовать пользовательский строковый класс, полученный из std::basic_string
, что-то вроде этого:
typedef wchar_t mychar_t; // say
class MyString : public std::basic_string <mychar_t>
{
...
};
Сразу же вы можете гибко выбирать размер кодовых единиц, хранящихся в вашем контейнере.,Но вы можете сделать гораздо больше, чем это.Например, с указанным выше объявлением (и после добавления в шаблон для различных конструкторов, которые вам нужно предоставить для пересылки их в std::basic_string
), вы все равно не можете сказать:
MyString s = "abcde";
Потому что «abcde»является узкой строкой и различные конструкторы для std::basic_string <wchar_t>
ожидают широкой строки.Microsoft решает эту проблему с помощью макроса (TEXT ("...")
или __T ("...")
), но это боль.Все, что нам нужно сделать сейчас, это предоставить подходящий конструктор в MyString
с подписью MyString (const char *s)
, и проблема будет решена.
На практике этот конструктор, вероятно, будет ожидать строку UTF-8, независимо от того,основной ширины символа, используемой для MyString
, и конвертируйте ее при необходимости.Кто-то комментирует здесь где-то, что вы должны хранить ваши строки как UTF-8, чтобы вы могли создавать их из литералов UTF-8 в вашем коде.Что ж, теперь мы нарушили это ограничение.Базовая ширина символов в наших строках может быть любой, какой мы захотим.
Еще одна вещь, о которой говорили в этой теме, это то, что find_first_of
может не работать должным образом для строк UTF-8 (и, действительно, некоторых UTF-16 тоже).Что ж, теперь вы можете предоставить реализацию, которая делает свою работу правильно.Должно занять около получаса.Если в std::basic_string
есть другие «сломанные» реализации (и я уверен, что они есть), то большинство из них, вероятно, могут быть заменены с такой же легкостью.
Что касается остальных, то в основном это зависит от того, какой уровеньабстракции вы хотите реализовать в своем классе MyString.Если ваше приложение удовлетворено, например, зависимостью от ICU, то вы можете просто предоставить несколько методов для преобразования в icu::UnicodeString
.Вероятно, именно так и поступит большинство людей.
Или, если вам нужно передать строки UTF-16 в / из собственных API-интерфейсов Windows, вы можете добавить методы для преобразования в const WCHAR *
и обратно (что опять-таки вы бы реализовали втаким образом, что они работают для всех значений mychar_t).Или вы можете пойти дальше и абстрагироваться от части или всей поддержки Unicode, предоставляемой используемой платформой и библиотекой.Mac, например, имеет богатую поддержку Unicode, но он доступен только в Objective-C, поэтому вам нужно обернуть его.Это зависит от того, насколько переносимым должен быть ваш код.
Таким образом, вы можете добавлять любые функциональные возможности, которые вам нравятся, возможно, на постоянной основе по мере выполнения работы, не теряя способности носить свои струны как std::basic_string
.Так или иначе.Просто попробуйте не писать код, который предполагает, что он знает, насколько он широк, или что он не содержит суррогатных пар .