c++gccendl

Where is endl manipulator defined


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 */

Solution

  • 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.