Why is it that wcout << ""; is OK but wcout << string(); is not?
Asked Answered
O

2

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?
}

Why does std::wcout accept a narrow string literal as its argument but doesn't accept a narrow string object?

Ogata answered 4/2, 2013 at 22:33 Comment(3)
error: no match for 'operator<<' in 'std::wcout << std::basic_string<char>(((const char*)"Hello"), (*(const std::allocator<char>*)(& std::allocator<char>())))'?Brittanybritte
+1 I've been puzzled by this IOStream weirdness too.Deery
why? coz stone cold said so! that's whyAnceline
P
8

This is dictated by § 27.7.3.6.4 of the C++11 Standard, where the following two overloaded operators (among others) are specified:

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

The last overload deals explicitly with char-based C-strings. This means that even for instantiations of the basic_ostream<> class template with the argument wchar_t there will be one overload which will deal with narrow char strings.

Moreover, per § 27.7.3.6.4/5:

Padding is determined as described in 22.4.2.2.2. The n characters starting at s are widened using out.widen (27.5.5.3). The widened characters and any required padding are inserted into out. Calls width(0).


On the other hand, the statement wcout << string("Hello"); does not compile because string does not have an implicit conversion to const char*, and because there is no overload of operator << that would insert a string built with one character type into an output stream with a different underlying character type.

In Standard terms (see § 21.4.8.9), here is how the definition of the overloaded operator << looks like for 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
    );

As you can see, the same template parameter charT is used to instantiate both basic_ostream and basic_string.

Percheron answered 4/2, 2013 at 22:49 Comment(0)
B
2

For the first one, I'm guessing this overload is used:

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

Where wstream is essentially a basic_ostream<wchar_t>.

For why string("Hello") doesn't work, it's simply because there is no conversion from string to wstring, nor an overload of operator<< provided.

Bidet answered 4/2, 2013 at 22:47 Comment(2)
Huh, funny. I assumed the second parameter would be const CharT * only.Moorefield
is it's simply because there is no conversion from wstring to string a typo? should it be it's simply because there is no conversion from string to wstring?Demirelief

© 2022 - 2024 — McMap. All rights reserved.