c++iostreammanipulators

Parametrized custom stream manipulators - why overload "operator<<"?


I am trying to implement a parametrized stream manipulator for a certain set of data. I do it the simple way as recommended:

class print_my_data
{
private:
    . . .

public:
    print_my_data(. . .) { . . . }

    ostream& operator()(std::ostream& out)
    {
        return out << . . . << endl;
    }
};

ostream& operator<<(ostream& out, print_my_data md) // <=== MY QUESTION BELOW IS ABOUT THIS
{
    return md(out);
}

Usage:

clog << print_my_data(. . .) << endl;

This works fine; but I really don't understand why it doesn't work unless I define operator<<! Why won't it call the same overloaded function as it does for endl?? (i.e. as an object that can be applied to the stream through operator())


Solution

  • The overload you're looking for is only defined for function pointers.

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

    Your print_my_data class is a callable object (a functor, in C++ terms). But it is not a function pointer. On the other hand, endl is a function, and hence has a function pointer (in fact, it's one of the few functions in the C++ standard library which do have an address)

    A not-unreasonable argument could be made that the overload should look like

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

    But alas, std::function wasn't around when the I/O manipulation operators were written. Neither were concepts, for that matter. And using SFINAE to declare

    template <typename F>
    basic_ostream& operator<<(
       F func);
    

    would have just opened an entire Pandora's box worth of messy details that the standards committee didn't want to deal with.