How do the stream manipulators work?

Narek picture Narek · Jan 8, 2011 · Viewed 10.5k times · Source

It is well known that the user can define stream manipulators like this:

ostream& tab(ostream & output)
{
    return output<< '\t';
} 

And this can be used in main() like this:

cout<<'a'<<tab<<'b'<<'c'<<endl;

Please explain me how does this all work? If operator<< assumes as a second parameter a pointer to the function that takes and returns ostream &, then please explain my why it is necessary? What would be wrong if the function does not take and return ostream & but it was void instead of ostream &?

Also it is interesting why “dec”, “hex” manipulators take effect until I don’t change between them, but user defined manipulators should be always used in order to take effect for each streaming?

Answer

CB Bailey picture CB Bailey · Jan 8, 2011

The standard defines the following operator<< overload in the basic_ostream class template:

basic_ostream<charT,traits>& operator<<(
    basic_ostream<charT,traits>& (*pf) (basic_ostream<charT,traits>&) );

Effects: None. Does not behave as a formatted output function (as described in 27.6.2.5.1).

Returns: pf(*this).

The parameter is a pointer to a function taking and returning a reference to a std::ostream.

This means that you can "stream" a function with this signature to an ostream object and it has the effect of calling that function on the stream. If you use the name of a function in an expression then it is (usually) converted to a pointer to that function.

std::hex is an std::ios_base manipulator defined as follows.

   ios_base& hex(ios_base& str);

Effects: Calls str.setf(ios_base::hex, ios_base::basefield).

Returns: str.

This means that streaming hex to an ostream will set the output base formatting flags to output numbers in hexadecimal. The manipulator doesn't output anything itself.