Today I'm trying to understand this thing related to the operator<< and its overloads.
Let's take a look at this code:
cout.operator<<("hello"); // +16 overloads -> implicit conversion to void*
cout.operator<<(123); // +16 overloads
operator<<(cout,"hello"); // +13 overloads
operator<<(cout, 123); // ERROR: no overload
cout << "hello"; // +13 overloads ---> non-member version!
cout << 123; // +16 overloads ---> member version!
cout << “hello”
Why isn't there a member
coutobject which takes a
Character strings are handled separately. Creating member operators for
std::basic_string would require all streams to have a dependancy on
std::basic_string functionality, which is not always desirable. All of the member operators are for built-in language types, but
std::basic_string is a class instead, so it has non-member operator overloads. One could argue that
const char (which decays to
const char*) is a built-in type, but
const char* similarly to
std::basic_string, and it doesn't make sense to split those implementations in two different areas of the library. Functionality for handling character strings, whether using arrays or classes, are usually grouped together.
Why isn't there a non-member operator<< which takes an integer?
Because there doesn't need to be one. It already exists as a member operator. You are not supposed to call member operators directly (unless you need to, which your example does not). You are supposed to just use the operator normally (
stream << ...) and let overload resolution pick the correct member or non-member operator, based on parameters, scoping, etc. If you think about it, a non-member overload would cause an ambiquity error. Should
stream << 123 call
::operator<<(stream, 123)? There can be only one choice, or the compile fails.
cout << “hello”choose the non-member version of the
operator<<? Maybe because there is a particular non-member
operator<<overload which is a good candidate for a
const char, rather than the member-
operator<<overload which takes a
That is exactly why. A typed
const char parameter is a better match for a narrow string literal then an untyped
void* pointer. So, if both operators are in scope (and the
const char overload is only in scope if you use
#include <string>), then the compiler will choose the better matching overload.