17
#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接受窄字符串文字作为其参数但不接受窄字符串对象?

4

2 回答 2

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
    );

最后一个重载显式处理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) 加宽。将加宽的字符和任何所需的填充插入到 out 中。调用宽度(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_ostreambasic_string

于 2013-02-04T22:49:21.863 回答
2

对于第一个,我猜这个重载被使用了:

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

本质wstream上是一个basic_ostream<wchar_t>.

为什么string("Hello")不起作用,这仅仅是因为没有从stringto的转换wstring,也没有提供的重载operator<<

于 2013-02-04T22:47:58.907 回答