这并没有什么特别之处。 std::ostream::operator<< 被简单地重载以接受各种类型的输入。
在操纵器函数的情况下,operator<< 被重载以默认接受某些类型的函数指针作为输入:
basic_ostream& operator<<(
std::ios_base& (*func)(std::ios_base&) );
basic_ostream& operator<<(
std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&) );
basic_ostream& operator<<(
std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );
然后这些重载的实现只是调用传递给它们的任何函数,指定*this作为函数的输入参数,例如:
basic_ostream& basic_ostream::operator<<(std::ios_base& (*func)(std::ios_base&) )
{
(*func)(*this);
return *this;
}
basic_ostream& basic_ostream::operator<<(std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&))
{
(*func)(*this);
return *this;
}
basic_ostream& basic_ostream::operator<<(std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&))
{
(*func)(*this);
return *this;
}
因此cout << std::endl; 只是调用cout.operator<<(std:endl);,其中std::endl() 匹配上面的第三个重载:
template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
在<iomanip> 标头中的流操纵器函数的情况下,不从用户代码中获取任何输入参数的操纵器(即std::boolalpha、std::showbase 等)通常实现为匹配的独立函数上述重载之一,因此直接将ostream/istream 作为参数传递。但是,从用户代码(即std::resetiosflags()、std::setbase() 等)获取输入参数的操纵器被定义为返回“未指定”(即实现定义)类型,其中它们的实现定义了operator<< 和@ 的额外重载987654340@ 用于这些类型,以便它们可以分别接收 ostream/istream 进行操作。
例如:std::fill 可以这样实现:
template< class CharT >
struct fill_t { CharT ch; };
template< class CharT >
fill_t setfill( CharT c )
{
return fill_t<CharT>{c};
}
template< class CharT >
basic_ostream& operator<<(basic_ostream& out, const fill_t &in)
{
out.fill(in.ch);
return out;
}
因此cout << setfill(' ') 调用等效于fill_t tmp = setfill(' '); operator<<(cout, tmp);