We know that endl
is manipulator and internally it put '\n'
to buffer and then flush up the buffer. Where is endl
defined? What is endl
, is it macro or function or variable or class or object? How can I define my own endl
manipulator?
cout << "hello" << endl ; /*what is endl and where it is defined */
std::endl
is a function template of signature:
template<class CharT, class Traits>
std::basic_ostream<CharT,Traits>& endl(std::basic_ostream<CharT,Traits>&);
The std::basic_ostream::operator<<
overload std::basic_ostream<CharT,Traits>>::operator<<(std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&))
accepts a function of a certain signature.
When you do std::cout << std::endl
, overload resolution is done on std::endl
, which determines the proper template types for std::endl
and instantiates a function. This then decays into a pointer, and is passed to operator<<
.
std::basic_ostream::operator<<
then calls the function on the ostream in question, and returns the return value. Something like:
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);
}
But the exact implementation is up to the compiler library writer1.
std::endl
causes a newline to be printed, and then tells the ostream to flush itself. You can emulate doing std::cout << std::endl;
via these two lines of code:
std::cout.put(std::cout.widen('\n'));
std::cout.flush();
How exactly std::endl
is implemented is up to the compiler, but the above is a decent approximation of how you might write it (naturally on a generic stream).
You are guaranteed to have access to std::endl
if you #include <ostream>
. You may have access to it if you include any other header file from the std
library. What file exactly defines it is again up to the implementation.
std::endl
is known as an "io manipulator". This technique is intended to allow functions that manipulate the io stream's state to be set up "inline" with output commands by chaining <<
calls together.
To create your own, if you want it to work with a single type of ostream, simply create a function that takes that kind of ostream
by reference, and returns it by reference. It is now an io manipulator.
If you want to handle a set of streams, create a template like:
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');
}
which is now an io manipulator that prints "bob"
. It can do whatever you want to the basic_ostream
in question.
An alternative plan is this:
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;
where bob
is now an object that can be used as an io manipulator.
1 This <<
overload is a function of type A->(A->A)->A
. Basically, instead of passing X to f, we pass X and f to <<
, which then does f(X)
. Pure syntactic sugar.
The fact that std::endl
is a template means that perfect forwarding it is a bit of a pain due to this technique. I end up defining stateless function endl_t
types, with an operator basic_ostream<CharT,Traits>&(*)(basic_ostream<CharT,Traits>&)()const
overload, so I can pass the overload set through perfect forwarding proxies sometimes.
Then we can pass the entire overload set of f:(A->A)
to <<
, and have the "next layer down" resolve the overload.
http://en.cppreference.com/w/cpp/io/manip/endl says:
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?
If you want to create it only for std::ostream
just create a function that accepts reference to std::ostream
and returns one. If you want to make it generic you can make it templatized, like std::endl
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With