为什么 std::endl 的类型推导失败?

Roh*_*ari 1 c++ auto type-deduction c++14

在以下代码中:

#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;
}
Run Code Online (Sandbox Code Playgroud)

for 的类型推导std::cout正确发生,但为什么它不适用于std::endl

注意:删除对运算符(与号)的引用也不起作用。


VS 代码说:

类型推导错误截图

编译器生成以下内容:

$ 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'
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 7

std::cout是一个具体类型std::ostream(又名特化std::basic_ostream<char>)的对象,所以auto可以推导出它的类型。

std::endl根本不是一个对象,它是一个模板函数(具体地说,一个以模板化std::basic_ostream对象为参数的流操纵器):

template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
Run Code Online (Sandbox Code Playgroud)

作为一个模板允许std::endl将工作与不同的字符类型的输出流(charwchar_t,等),即std::coutVSstd::wcout等。

但是,您没有为模板参数提供任何值来告诉编译器std::endl您要使用哪种专业化,因此auto无法为其推导出具体类型,因此会出现错误。

你将不得不做这样的事情:

auto& end = std::endl<char, std::char_traits<char>>;
Run Code Online (Sandbox Code Playgroud)

现场演示