Most IO stream manipulators are regular functions with the following signature:
std::ios_base& func( std::ios_base& str );
However
You need to put << before the endl. It is a member of ofstream:
namespace std {
template <class charT, class traits = char_traits<charT> >
class basic_ostream {
public:
basic_ostream<charT,traits>& operator<<(
basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
// ...
};
}
endl works like a "/n" to skip the line, so you need a cout line to skip
Given a statement expression of the form
std::cout << std::endl;
The compiler has information about the type of std::cout - which is a specialisation of the templated std::basic_ostream which looks something like (omitting the containing namespace std).
template <class charT, class traits = char_traits<charT> >
class basic_ostream
{
public:
basic_ostream<charT,traits>& operator<<(
basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
};
Since the compiler has information about the type of std::cout it knows what charT and traits are to specialise the preceeding template.
The above causes std::endl in the expression std::cout << std::endl to match to the specific std::basic_ostream<charT, traits>& endl( std::basic_ostream<charT, traits>&).
The reason type deduction doesn't work in
auto myendl = std::endl;
is because std::endl is a templated function, and this declaration provides no information to specialise that template (i.e. picking what charT or traits are). If it can't specialise the templated std::endl, it can't infer that function's return type, so the type deduction fails.
The operator<< in question is a member of std::basic_ostream:
namespace std {
template <class charT, class traits = char_traits<charT> >
class basic_ostream {
public:
basic_ostream<charT,traits>& operator<<(
basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
// ...
};
}
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<char, std::char_traits<char>>, aka std::ostream. So the member function of cout looks like
std::ostream& operator<<(std::basic_ostream<char, std::char_traits<char>>& (*pf)
(std::basic_ostream<char, std::char_traits<char>>&));
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<char, std::char_traits<char>>& (*pf)
(std::basic_ostream<char, std::char_traits<char>>&) = std::endl;
Because basic_ostream has a templated overload of operator<< that expects just such a function pointer:
basic_ostream<charT, traits>& operator<<(basic_ios<charT, traits>& (*pf)(basic_ios<charT, traits>&));