Назначение "const char *" для std :: string разрешено, но назначение для std :: wstring не компилируется. Зачем? - PullRequest
4 голосов
/ 06 декабря 2009

Я предположил, что std :: wstring и std :: string оба предоставляют более или менее одинаковый интерфейс.

Поэтому я попытался включить возможности Unicode для нашего приложения

# ifdef APP_USE_UNICODE
    typedef std::wstring AppStringType;
# else
    typedef std::string  AppStringType;
# endif

Однако, это дает мне много ошибок компиляции, когда используется -DAPP_USE_UNICODE.

Оказалось, что компилятор задыхается, когда const char[] назначено std::wstring.

РЕДАКТИРОВАТЬ : улучшен пример, исключив использование литерала "привет".

#include <string>

void myfunc(const char h[]) {
   string  s = h; // compiles OK
   wstring w = h; // compile Error
}

Почему это так важно?

Назначение const char* для std::string разрешено, но присвоение std::wstring дает ошибки компиляции.

Разве std::wstring не должен обеспечивать тот же интерфейс, что и std::string? Хотя бы для такой базовой операции, как присваивание?

(среда: gcc-4.4.1 в Ubuntu Karmic 32bit)

Ответы [ 7 ]

11 голосов
/ 06 декабря 2009

Вы должны сделать:

#include <string>

int main() {
  const wchar_t h[] = L"hello";
  std::wstring w = h;
  return 0;
}

std::string - это определение типа std::basic_string<char>, а std::wstring - это определение типа std::basic_string<wchar_t>. Таким образом, «эквивалентная» C-строка wstring является массивом wchar_t s.

'L' перед строковым литералом означает, что вы используете строковую константу с широким символом.

6 голосов
/ 06 декабря 2009

Соответствующей частью строкового API является этот конструктор:

basic_string(const charT*);

Для std :: string charT - это char. Для std :: wstring это wchar_t. Поэтому причина, по которой он не компилируется, заключается в том, что в wstring нет конструктора char *. Почему у wstring нет конструктора char *

Не существует единственного уникального способа преобразования строки char в строку wchar. Какая кодировка используется с символьной строкой? Это всего лишь 7 бит ASCII? Это UTF-8? Это UTF-7? Это SHIFT-JIS? Так что я не думаю, что для std :: wstring было бы полностью разумно автоматически конвертировать из char *, даже если бы вы могли охватить большинство случаев. Вы можете использовать:

w = std::wstring(h, h + sizeof(h) - 1);

, который преобразует каждый символ по очереди в wchar (кроме терминатора NUL), и в этом примере это, вероятно, то, что вы хотите. Однако, как говорит int3, если вы это имеете в виду, то, скорее всего, лучше использовать широкий строковый литерал.

1 голос
/ 06 декабря 2009

Для преобразования из многобайтовой кодировки в кодировку широких символов взгляните на заголовок <locale> и тип std::codecvt. Библиотека Dinkumware имеет класс Dinkum::wstring_convert, который облегчает выполнение таких многобайтовых преобразований в широкие.

Функция std::codecvt_byname позволяет найти экземпляр codecvt для конкретной именованной кодировки. К сожалению, обнаружение имен кодировок (или локалей) в вашей системе зависит от реализации.

1 голос
/ 06 декабря 2009

Небольшое предложение ... Не используйте строки "Unicode" под Linux (широкие строки a.k.a.). std::string прекрасно работает и очень хорошо держит Unicode (UTF-8).

Большинство Linux API работают со char * строками, а самая популярная кодировка - UTF-8.

Итак ... Только не беспокойтесь, используя wstring.

0 голосов
/ 06 декабря 2009

Похоже, вы можете сделать что-то вроде этого:

    #include <sstream>
    // ...
    std::wstringstream tmp;
    tmp << "hello world";
    std::wstring our_string = 

Хотя для более сложной ситуации вы можете разбить и использовать mbstowcs

0 голосов
/ 06 декабря 2009

В дополнение к другим ответам, вы можете использовать трюк из книги Microsoft (в частности, tchar.h) и написать что-то вроде этого:

# ifdef APP_USE_UNICODE
    typedef std::wstring AppStringType;
    #define _T(s) (L##s)
# else
    typedef std::string  AppStringType;
    #define _T(s) (s)
# endif

AppStringType foo = _T("hello world!");

(Примечание: мой макро-фу слаб, и это не проверено, но вы поняли.)

0 голосов
/ 06 декабря 2009

вы должны использовать

#include <tchar.h>

tstring вместо wstring / string TCHAR * вместо символа * и _T ("привет") вместо "привет" или L "привет"

при использовании _UNICODE будет использоваться соответствующая форма string + char.

...