Почему это так? в порядке, но wcout << string(); не является? - программирование

Почему это так? в порядке, но wcout << string(); не является?

#include <iostream>
#include <string>

using namespace std;

int main()
{
    wcout << L"Hello";          // OK.
    wcout << wstring(L"Hello"); // OK.
    wcout << "Hello";           // OK. Why?
    wcout << string("Hello");   // Error. Why?
}

Почему std::wcout принимает узкий строковый литерал как свой аргумент, но не принимает узкий строковый объект?

4b9b3361

Ответ 1

Это продиктовано § 27.7.3.6.4 стандарта С++ 11, в котором указаны следующие два перегруженных оператора (среди прочего):

template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(
    basic_ostream<charT,traits>& out, 
    const charT* s
    );

template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(
    basic_ostream<charT,traits>& out, 
    const char* s
    );

Последняя перегрузка напрямую связана с C-строками на основе char. Это означает, что даже для экземпляров шаблона класса basic_ostream<> с аргументом wchar_t будет одна перегрузка, которая будет обрабатывать узкие строки char.

Кроме того, согласно § 27.7.3.6.4/5:

Заполнение определяется, как описано в 22.4.2.2.2. n символов, начинающихся с s, расширяются с использованием out.widen(27.5.5.3). Расширяемые символы и любое требуемое заполнение вставляются в. Ширина вызовов (0).


С другой стороны, оператор wcout << string("Hello"); не компилируется, потому что string не имеет неявного преобразования в const char*, и потому что нет перегрузки operator <<, который вставлял бы string, построенный с одним типом символа в выходной поток с другим типом базового символа.

В стандартных терминах (см. § 21.4.8.9), вот как выглядит определение перегруженного operator << для std::string:

template<class charT, class traits, class Allocator>
basic_ostream<charT, traits>& operator<<(
    basic_ostream<charT, traits>& os,
    const basic_string<charT,traits,Allocator>& str
    );

Как вы можете видеть, тот же параметр шаблона charT используется для создания экземпляров как basic_ostream, так и basic_string.

Ответ 2

Для первого, я предполагаю эта перегрузка используется:

template< class CharT, class Traits >
basic_ostream<CharT,Traits>& operator<<( basic_ostream<CharT,Traits>& os, 
                                         const char* s );

Где wstream по существу a basic_ostream<wchar_t>.

Для чего string("Hello") не работает, это просто потому, что нет преобразования от string до wstring, а также перегрузки operator<<.