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

99 Views Asked by At

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())

1

There are 1 best solutions below

1
On BEST ANSWER

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.