endl操纵器在哪里定义

Nir*_*mar 3 c++ gcc endl

我们知道这endl是操纵器,在内部它放入'\n'缓冲区然后刷新缓冲区.在哪里endl定义?什么是endl宏,函数或变量,类或对象?我怎样才能定义自己的endl操纵器?

cout << "hello" << endl ; /*what is endl and  where it is defined */
Run Code Online (Sandbox Code Playgroud)

Yak*_*ont 14

std::endl 是签名的功能模板:

template<class CharT, class Traits>
std::basic_ostream<CharT,Traits>& endl(std::basic_ostream<CharT,Traits>&);
Run Code Online (Sandbox Code Playgroud)

所述std::basic_ostream::operator<<过载std::basic_ostream<CharT,Traits>>::operator<<(std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&))接受某个签名的函数.

执行此操作时,将执行std::cout << std::endl重载解析std::endl,这将确定适当的模板类型std::endl并实例化函数.然后它衰减成指针,并传递给operator<<.

std::basic_ostream::operator<<然后在有问题的ostream上调用函数,并返回返回值.就像是:

template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>&
std::basic_ostream<CharT, Traits>::operator<<(
  std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&)
) {
  return func(*this);
}
Run Code Online (Sandbox Code Playgroud)

但确切的实现取决于编译器库编写器1.

std::endl导致打印换行符,然后告诉ostream自行刷新.您可以std::cout << std::endl;通过以下两行代码模拟:

std::cout.put(std::cout.widen('\n'));
std::cout.flush();
Run Code Online (Sandbox Code Playgroud)

究竟std::endl是如何实现的,取决于编译器,但上面是你可以编写它的一个不错的近似值(当然是在通用流上).

你肯定有机会获得std::endl,如果你#include <ostream>.如果您包含std库中的任何其他头文件,则可以访问它.准确定义它的文件又取决于实现.

std::endl被称为"io操纵者".此技术旨在通过将<<调用链接在一起,允许通过输出命令将操纵io流状态的函数设置为"内联" .

要创建自己的,如果您希望它使用单一类型的ostream,只需创建一个ostream通过引用采用这种类型的函数,并通过引用返回它.它现在是一个io操纵者.

如果要处理一组流,请创建一个模板,如:

template<class CharT, class Traits>
std::basic_ostream<CharT, Traits>& bob(std::basic_ostream<CharT, Traits>& os)
{
  return os << os.widen('b') << os.widen('o') << os.widen('b');
}
Run Code Online (Sandbox Code Playgroud)

现在是一个打印的io操纵器"bob".它可以做任何你想要的basic_ostream问题.

另一个计划是:

struct bob_t {
  template<class OS>
  OS& operator()(OS& os)const {
    return os << os.widen('b') << os.widen('o') << os.widen('b');
  }
  template<class OS>
  operator OS&(*)(OS&)() const {
    return [](OS& os)->OS&{ return bob_t{}(os); };
  }
};
static const bob_t bob;
Run Code Online (Sandbox Code Playgroud)

bob现在在哪里可以用作io操纵器的对象.


1<<重载是类型的函数A->(A->A)->A.基本上,我们不是将X传递给f,而是传递X和f <<,然后传递f(X).纯合成糖.

std::endl作为模板的事实意味着由于这种技术的完美转发它有点痛苦.我最终定义了无状态函数endl_t类型,带有operator basic_ostream<CharT,Traits>&(*)(basic_ostream<CharT,Traits>&)()const重载,所以我有时可以通过完美转发代理传递重载集.

然后我们可以将整个重载集传递f:(A->A)<<,并让"下一层"解决过载.