#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
接受一个狭窄的字符串文字作为其参数但不接受一个狭窄的字符串对象?
答案 0 :(得分: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<>
的{{1}}类模板的实例化,也会有一个重载将处理窄wchar_t
字符串。
此外,根据§27.7.3.6.4/ 5:
填充如22.4.2.2.2中所述确定。 使用out.widen(27.5.5.3)扩展从s开始的n个字符。加宽的字符和任何所需的填充都插入。调用宽度(0)。
<小时/> 另一方面,语句
char
无法编译,因为wcout << string("Hello");
没有隐式转换为string
,并且因为没有const char*
的重载会插入operator <<
使用一种字符类型构建到具有不同基础字符类型的输出流中。
在标准术语中(参见§21.4.8.9),以下是string
的重载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
。
答案 1 :(得分:2)
对于第一个,我猜是使用了this overload:
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")
不起作用,只是因为没有从string
到wstring
的转换,也没有提供operator<<
的重载。