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