Most IO stream manipulators are regular functions with the following signature:
std::ios_base& func( std::ios_base& str );
However
The operator<< in question is a member of std::basic_ostream:
namespace std {
template >
class basic_ostream {
public:
basic_ostream& operator<<(
basic_ostream& (*pf)(basic_ostream&));
// ...
};
}
Since the call is to std::cout << std::endl, or equivalently std::cout.operator<<(std::endl), we already know the exact instantiation of basic_ostream: std::basic_ostream, aka std::ostream. So the member function of cout looks like
std::ostream& operator<<(std::basic_ostream>& (*pf)
(std::basic_ostream>&));
This member function is not a function template, just an ordinary member function. So the question remaining, is can it be called with the name std::endl as an argument? Yes, initializing the function argument is equivalent to a variable initialization, as though we had written
std::basic_ostream>& (*pf)
(std::basic_ostream>&) = std::endl;