Ответ 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
.