Портативный wchar_t в C ++ - PullRequest
5 голосов
/ 22 января 2009

Есть ли переносимый wchar_t в C ++? На Windows его 2 байта. На все остальное 4 байта. Я хотел бы использовать wstring в своем приложении, но это вызовет проблемы, если я решу в будущем перенести его.

Ответы [ 4 ]

4 голосов
/ 22 января 2009

Если вы имеете дело с внутренним использованием программы, не беспокойтесь об этом; wchar_t в классе A такой же, как в классе B.

Если вы планируете передавать данные между версиями Windows и Linux / MacOSX, вам нужно беспокоиться не только о wchar_t, и вам нужно найти средства для обработки всех деталей.

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

Что-то вроде typedef int my_char; typedef std::basic_string<my_char> my_string;

3 голосов
/ 22 января 2009

Что вы подразумеваете под "портативным wchar_t"? Существует тип uint16_t шириной 16 бит, который часто доступен. Но это, конечно, еще не составляет строку. Строка должна знать о своей кодировке, чтобы иметь смысл таких функций, как length(), substring() и т. Д. (Поэтому она не обрезает символы в середине кодовой точки при использовании utf8 или 16). Я знаю несколько строковых классов, совместимых с юникодом, которые вы можете использовать. Все они могут быть использованы в коммерческих программах бесплатно (Qt one будет совместим с коммерческими программами бесплатно через пару месяцев, когда выйдет Qt 4.5).

ustring из проекта gtkmm. Если вы программируете с помощью gtkmm или используете glibmm, это должно быть первым выбором, он использует utf-8 для внутреннего использования. Qt также имеет строковый класс, называемый QString. Это закодировано в utf-16. ICU - это еще один проект, который создает переносимые классы строковых юникодов и имеет класс UnicodeString, который, кажется, внутренне закодирован в utf-16, как Qt. Хотя я этим не пользовался.

1 голос
/ 20 августа 2010

Предлагаемый стандарт C ++ 0x будет иметь типы char16_t и char32_t. До этого вам придется использовать целые числа для не-1003 * символов.

#if defined(__STDC_ISO_10646__)
    #define WCHAR_IS_UTF32
#elif defined(_WIN32) || defined(_WIN64)
    #define WCHAR_IS_UTF16
#endif

#if defined(__STDC_UTF_16__)
    typedef _Char16_t CHAR16;
#elif defined(WCHAR_IS_UTF16)
    typedef wchar_t CHAR16;
#else
    typedef uint16_t CHAR16;
#endif

#if defined(__STDC_UTF_32__)
    typedef _Char32_t CHAR32;
#elif defined(WCHAR_IS_UTF32)
    typedef wchar_t CHAR32;
#else
    typedef uint32_t CHAR32;
#endif

В соответствии со стандартом вам нужно будет специализировать char_traits для целочисленных типов. Но в Visual Studio 2005 я получил std::basic_string<CHAR32> без специальной обработки.

Я планирую использовать базу данных SQLite.

Тогда вам нужно будет использовать UTF-16, а не wchar_t.

API SQLite также имеет версию UTF-8. Вы можете использовать это вместо того, чтобы иметь дело с wchar_t различиями.

0 голосов
/ 20 августа 2010

Мое предложение. Используйте UTF-8 и std :: string. Широкие струны не принесут вам слишком много добавленной стоимости. Поскольку вы все равно не можете интерпретировать широкие символы как буквы, так как некоторые символы записаны в нескольких кодовых точках Юникода.

Так что используйте где угодно UTF-8 и используйте хорошую библиотеку для работы с естественными языками. Как например Boost.Locale.

Плохая идея: определять что-то вроде typedef uint32_t mychar; плохо. Поскольку вы не можете использовать iostream с ним, вы не можете создать, например, stringstream, основанный на этом символе, поскольку вы не сможете писать в нем.

Например, это не будет работать:

std::basic_ostringstream<unsigned> s;
ss << 10;

Не создаст вам строку.

...