Search code examples
c++c++14autotype-deduction

Why does the type deduction for std::endl fails?


In the following code:

#include <iostream>

auto& print = std::cout; // Type deduction for std::cout works
auto& end = std::endl;   // But the std::endl is exception here

int main(void) {
  print << "Hello" << end;

  return 0;
}

The type deduction for std::cout takes place properly, but why doesn't it works for std::endl?

Note: Removing the reference to operator (ampersand) doesn't works either.


The VS Code says:

Type deduction error screenshot

And the compiler generates the following:

$ g++ -Wall -O3 -std=c++14 -o main main.cpp; ./main

main.cpp:4:18: error: unable to deduce 'auto&' from 'std::endl'
    4 | auto& end = std::endl;    // But the std::endl is exception here
      |                  ^~~~
main.cpp:4:18: note:   couldn't deduce template parameter 'auto'

Solution

  • std::cout is an object of a concrete type std::ostream (aka the std::basic_ostream<char> specialization), so auto can deduce its type.

    std::endl is not an object at all, it is a template function (specifically, a stream manipulator taking a templated std::basic_ostream object as a parameter):

    template< class CharT, class Traits >
    std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
    

    Being a template allows std::endl to work with output streams of different character types (char, wchar_t, etc), ie std::cout vs std::wcout, etc.

    But, you are not providing any values for the template parameters to tell the compiler which specialization of std::endl you want to use, so auto can't deduce a concrete type for it, hence the error.

    You would have to do something like this instead:

    auto& end = std::endl<char, std::char_traits<char>>;
    

    Live Demo