Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obscure C++ operator overloading

I have the following code:

#include <iostream>

using namespace std;

ostream& f(ostream& os) {
    return os << "hi";
}

int main() {
    cout << "hello " << f << endl;
    return 0;
}

And somehow this works - the output is "hello hi". How does this get interpreted by the compiler? I don't understand how a function can be inserted into a stream.

like image 589
hovnatan Avatar asked Nov 28 '15 12:11

hovnatan


2 Answers

std::ostream has an operator<< overload that receives a pointer to a function with the signature such as the one you wrote (number 11 in this list):

basic_ostream& operator<<(
    std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );

which just calls the given function passing itself as argument. This overload (along with several similar others) is there to allow you to implement stream manipulators, i.e. stuff that you output in the stream with an << and changes the state of the stream from there. For example, our version of the (incorrectly) ubiquitous std::endl may be implemented as

std::ostream &myendl(std::ostream &s) {
    s<<'\n';
    s.flush();
    return s;
}

which can then be used exactly as the "regular" std::endl:

std::cout<<"Hello, World!"<<myendl;

(the actual implementation is templated and a bit more complicated because it has to work even with wide streams, but you got the idea)

like image 72
Matteo Italia Avatar answered Oct 15 '22 02:10

Matteo Italia


std::ostream::operator<< has an overload which accepts a function as parameter; and the body of that overload is to invoke the function given.

This is exactly how endl works in fact. endl is actually a function similar to:

ostream &endl(ostream &os)
{
    os << '\n'; 
    os.flush(); 
    return os;
}
like image 31
M.M Avatar answered Oct 15 '22 02:10

M.M