endl操纵器在哪里定义
Where is endl manipulator defined
我们知道 endl
是操纵器,它在内部将 '\n'
放入缓冲区,然后刷新缓冲区。 endl
在哪里定义的?什么是endl
,是宏还是函数还是变量还是class还是对象?如何定义自己的 endl
操纵器?
cout << "hello" << endl ; /*what is endl and where it is defined */
http://en.cppreference.com/w/cpp/io/manip/endl 说:
Defined in header <ostream>
template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
if i want to code my own endl manipulator what code i will have to write?
如果您只想为 std::ostream
创建它,只需创建一个接受对 std::ostream
和 returns 的引用的函数。如果你想让它通用,你可以让它模板化,比如 std::endl
.
std::endl
为签名函数模板:
template<class CharT, class Traits>
std::basic_ostream<CharT,Traits>& endl(std::basic_ostream<CharT,Traits>&);
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 上的函数,并且 return 是 return 值。类似于:
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);
}
但具体实现取决于编译库作者1.
std::endl
导致打印换行符,然后告诉 ostream 刷新自身。您可以通过以下两行代码模拟执行 std::cout << std::endl;
:
std::cout.put(std::cout.widen('\n'));
std::cout.flush();
std::endl
的具体实现方式取决于编译器,但以上是您可能如何编写它的一个不错的近似值(自然地在通用流上)。
如果您 #include <ostream>
,您保证可以访问 std::endl
。如果您包含 std
库中的任何其他头文件,您可能可以访问它。什么文件准确定义它又取决于实现。
std::endl
被称为 "io manipulator"。此技术旨在允许通过将 <<
调用链接在一起来使用输出命令来设置操纵 io 流状态的函数 "inline"。
要创建你自己的,如果你想让它与单一类型的 ostream 一起工作,只需创建一个函数,通过引用接受那种 ostream
,然后通过引用来 return .它现在是一个 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');
}
现在是一个打印 "bob"
的 io 操纵器。它可以对有问题的 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;
其中 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)
的整个重载集传递给 <<
,并让 "next layer down" 解析重载。
我们知道 endl
是操纵器,它在内部将 '\n'
放入缓冲区,然后刷新缓冲区。 endl
在哪里定义的?什么是endl
,是宏还是函数还是变量还是class还是对象?如何定义自己的 endl
操纵器?
cout << "hello" << endl ; /*what is endl and where it is defined */
http://en.cppreference.com/w/cpp/io/manip/endl 说:
Defined in header
<ostream>
template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
if i want to code my own endl manipulator what code i will have to write?
如果您只想为 std::ostream
创建它,只需创建一个接受对 std::ostream
和 returns 的引用的函数。如果你想让它通用,你可以让它模板化,比如 std::endl
.
std::endl
为签名函数模板:
template<class CharT, class Traits>
std::basic_ostream<CharT,Traits>& endl(std::basic_ostream<CharT,Traits>&);
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 上的函数,并且 return 是 return 值。类似于:
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);
}
但具体实现取决于编译库作者1.
std::endl
导致打印换行符,然后告诉 ostream 刷新自身。您可以通过以下两行代码模拟执行 std::cout << std::endl;
:
std::cout.put(std::cout.widen('\n'));
std::cout.flush();
std::endl
的具体实现方式取决于编译器,但以上是您可能如何编写它的一个不错的近似值(自然地在通用流上)。
如果您 #include <ostream>
,您保证可以访问 std::endl
。如果您包含 std
库中的任何其他头文件,您可能可以访问它。什么文件准确定义它又取决于实现。
std::endl
被称为 "io manipulator"。此技术旨在允许通过将 <<
调用链接在一起来使用输出命令来设置操纵 io 流状态的函数 "inline"。
要创建你自己的,如果你想让它与单一类型的 ostream 一起工作,只需创建一个函数,通过引用接受那种 ostream
,然后通过引用来 return .它现在是一个 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');
}
现在是一个打印 "bob"
的 io 操纵器。它可以对有问题的 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;
其中 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)
的整个重载集传递给 <<
,并让 "next layer down" 解析重载。