1

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'
Rohan Bari
  • 7,482
  • 3
  • 14
  • 34
  • 1
    You really shouldn't try to rename standard library constructs like that. – Nicol Bolas Aug 09 '20 at 18:41
  • @NicolBolas I understand it. I was so confused when I saw it working with `std::cout` but not in case with `std::cin`. Searched about it, but doesn't seems I found something relevant about this problem. – Rohan Bari Aug 09 '20 at 18:41
  • Did you write this code based on [this question](https://stackoverflow.com/questions/63329779/)? Specifically, [this answer](https://stackoverflow.com/a/63329879/65863), which shows the `auto& print = std::cout;` trick, but also says "*Since `std::endl` is a template function and not a type, **it can't be deduced using the reference to `auto` type**.*" – Remy Lebeau Aug 09 '20 at 19:16
  • @RemyLebeau Yes, I wrote that as soon as I get understand the reason. And it was peculiar stuff that `std::endl` didn't work that time. I had no idea about it. – Rohan Bari Aug 09 '20 at 19:17
  • 1
    Most of the time you don't need `std::endl`. `auto end = '\n'` would work just as well (And you could just write `"Hello\n"`). – Artyer Aug 09 '20 at 19:44
  • **DO NOT post images of code, data, error messages, etc.** - copy or type the text into the question. [ask] – Rob Mar 03 '21 at 01:04
  • Does this answer your question? [Can we rename cout, endl keyword in cpp?](https://stackoverflow.com/questions/63329779/can-we-rename-cout-endl-keyword-in-cpp) – Casey Mar 03 '21 at 04:34

1 Answers1

7

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

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • @RohanBari [templates](https://en.cppreference.com/w/cpp/language/templates) is a very complex topic, there are whole chapters, and even whole books, on the subject. I strongly suggest you get yourself some [good C++ books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) to read. – Remy Lebeau Aug 09 '20 at 19:01