Обрабатывать std :: basic_string <> с аргументами разных типов - PullRequest
1 голос
/ 17 октября 2010

Я хочу реализовать библиотеку c ++, и, как и многим другим библиотекам, мне нужно принимать строковые аргументы от пользователя и возвращать строки.Текущий стандарт определяет std :: string и std :: wstring (я предпочитаю wstring).Теоретически я должен реализовать методы со строковыми аргументами дважды:

virtual void foo(std::string &) = 0; // convert internally from a previous defined charset to unicode
virtual void foo(std::wstring &) = 0;

C ++ 0x не облегчает жизнь, для char16_t и char32_t мне нужно:

virtual void foo(std::u16string &) = 0;
virtual void foo(std::u32string &) = 0;

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

Другая проблема заключается в том, хочет ли пользователь (или я) работать с пользовательскими распределителями или настроенными классами свойств:все, что приводит к совершенно новому типу.Например, для написания пользовательских специализаций codecvt для многобайтовых кодировок, стандарт говорит, что я должен ввести пользовательский тип state_type, для которого требуется специальный класс свойств, который приводит к новому типу std :: basic_ifstream <>, и это полностью несовместимо с интерфейсами, ожидающими std.:: ifstream & в качестве аргумента.

Одним из решений -possible- является создание каждого библиотечного класса в качестве шаблона, который управляет типом-значением, признаками и распределителями, указанными пользователем.Но это излишне и делает абстрактные базовые классы (интерфейсы) невозможными.

Другое решение - просто указать один тип (например, u32string) по умолчанию, каждый пользователь должен передавать данные с использованием этого типа.Но теперь подумайте о проекте, который использует 3 библиотеки, а первая библиотека использует u32string, вторую библиотеку u16string и третью библиотеку wstring -> HELL.

Что я действительно хочу, так это объявить метод как void foo (put_unicode_string_here) - без представления моего собственного класса UnicodeString или UnicodeStream.

Ответы [ 2 ]

1 голос
/ 17 октября 2010

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

UPDATE :с другой стороны, вы можете шаблонизировать весь свой код и оставить std::basic_string<T> в качестве шаблона во всем коде.Это только запутывается, если вы делаете разные вещи в зависимости от размера аргумента шаблона.

0 голосов
/ 29 апреля 2011

char_traits действительно безнадежно ужасный мусорный бак случайных черт.Должна ли каждая строка предварительно указывать максимальный поддерживаемый размер файла, чувствительность к регистру и (ugh) тип состояния самого механизма кодирования?НЕТ.

Однако то, что вы просите, невозможно даже с хорошо продуманными чертами.string и wstring существенно различаются, потому что размер внутреннего типа символа отличается.Для запуска любого вида алгоритма вам нужно запросить объект для char_t.Для этого требуются RTTI или виртуальные функции, потому что basic_string не поддерживает (и не должна) поддерживать эту информацию во время выполнения.

Одно-возможное решение - создать каждый класс библиотеки как шаблон, который управляетvalue_type, признаки и распределители, указанные пользователем.Но это излишне и делает невозможным абстрактные базовые классы (интерфейсы).

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

Другое решение - просто указать один тип (например, u32string) по умолчанию, каждый пользователь должен передавать данные, используяэтот тип.Но теперь подумайте о проекте, который использует 3 библиотеки, а первая библиотека использует u32string, вторую библиотеку u16string и третью библиотеку wstring -> HELL.

Вот почему я напуган C +«11» улучшенная поддержка Unicode.Это упрощает прямое взаимодействие с данными файла и препятствует абстракции к внутреннему формату common wchar_t.Было бы лучше, если бы требовались специальные кодовые значения для UTF-16 и UTF-32 и указывать, что wchar_t должно быть не менее 21 бита.Если раньше среди чистых интерфейсов C ++ были только «тупые» char и «умные» библиотеки wchar_t, нам, возможно, приходилось бороться с дополнительной шириной, а char16_t - это просто мгновенный красный флаг.

Но это в будущем.

Если вы действительно используете несколько несовместимых библиотек, и проблема заключается в перемещении данных между функциями, требующими различных форматов, то напишите утилиту ScopeGuard-style конвертировать из и обратно в выбранный вами общий формат, например wstring.Эта утилита может быть шаблоном с явной специализацией для каждого необходимого несовместимого формата или набором шаблонов без шаблонов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...