Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is operator<< function between std::ostream and char a non-member function?

Tags:

c++

c++11

ostream

When I ran the following program

#include <iostream>  int main() {    char c = 'a';    std::cout << c << std::endl;    std::cout.operator<<(c) << std::endl;     return 0; } 

I got the output

a 97 

Digging further at http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt, I noticed that std::ostream::operator<<() does not have an overload that has char as the argument type. The function call std::cout.operator<<(a) gets resolved to std::ostream::operator<<(int), which explains the output.

I am assuming that the operator<< function between std::ostream and char is declared elsewhere as:

std::ostream& operator<<(std::ostream& out, char c); 

Otherwise, std::cout << a would resolve to std::ostream::operator<<(int).

My question is why is that declared/defined as a non-member function? Are there any known issues that prevent it from being a member function?

like image 824
R Sahu Avatar asked Jul 07 '15 16:07

R Sahu


People also ask

Why are << and >> operators Cannot be overloaded using member functions?

These operators cannot be overloaded because if we overload them it will make serious programming issues. For an example the sizeof operator returns the size of the object or datatype as an operand. This is evaluated by the compiler.

Could we define operator << as a member function?

You can not do it as a member function, because the implicit this parameter is the left hand side of the << -operator. (Hence, you would need to add it as a member function to the ostream -class.

What is this operator << in C++?

In C++, stream insertion operator “<<” is used for output and extraction operator “>>” is used for input.

What is std :: ostream?

The std::ostream , the std::istream or the std::iostream are base classes of stream types (e.g. std::stringstream , std::fstream , etc.) in the Standard Library. These classes are protected against instantiation, you can instantiate their derived classes only.


2 Answers

The set of inserters for std::basic_ostream includes partial specializations for inserting char, signed char, unsigned char and such into basic_ostream<char, ...> streams. Note that these specializations are made available for basic_ostream<char, ...> streams only, not for basic_ostream<wchar_t, ...> streams or streams based on any other character type.

If you move these freestanding templates into the main basic_ostream definition, they will become available for all specializations forms of basic_ostream. Apparently, library authors wanted to prevent this from happening.

I don't really know why they wanted to introduce these specializations on top of the more generic

template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,                                         char); 

inserter, but apparently they had their reasons (optimization?).

The same situation exists for C-string inserters. In addition to the more generic inserter

template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,                                         const char*); 

the library specification also declares more specific

template<class traits> basic_ostream<char,traits>& operator<<(basic_ostream<char,traits>&,                                        const char*); 

and so on.

like image 136
AnT Avatar answered Oct 15 '22 00:10

AnT


One reason is following the general C++ advice of preferring non-member non-friend functions to member functions. This is item 23 in Scott Meyer's Effective C++. This is discussed in stackoverflow.

like image 31
snow_abstraction Avatar answered Oct 14 '22 23:10

snow_abstraction