为什么wcout <<""; 没问题,但是wcout << string(); 不是?

xml*_*lmx 16 c++ string encoding iostream

#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?
}
Run Code Online (Sandbox Code Playgroud)

为什么std::wcout接受一个狭窄的字符串文字作为其参数但不接受一个狭窄的字符串对象?

And*_*owl 8

这由C++ 11标准的第27.7.3.6.4节规定,其中指定了以下两个重载运算符(以及其他):

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
    );
Run Code Online (Sandbox Code Playgroud)

最后一次重载明确地处理char基于C的字符串.这意味着即使对于basic_ostream<>带有参数的类模板的实例化,wchar_t也会有一个重载将处理窄char字符串.

此外,根据§27.7.3.6.4/ 5:

填充如22.4.2.2.2中所述确定.从s开始的n个字符使用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
    );
Run Code Online (Sandbox Code Playgroud)

如您所见,相同的模板参数charT用于实例化basic_ostreambasic_string.