Bjarne是错误的这个ADL的例子,还是我有一个编译器错误?

我正在阅读关于参数相关查找 的C ++编程语言第4版 (由Bjarne Stroustrup撰写 )。 这里是引用(26.3.6,过度的ADL):

依赖于参数的查找(通常称为ADL)对于避免冗长是非常有用的(14.2.4)。 例如:

#include <iostream> int main() { std::cout << "Hello, world" << endl; // OK because of ADL } 

没有依赖于参数的查找, endl操纵器将不会被发现。 实际上,编译器注意到<<的第一个参数是std定义的一个ostream 。 因此,它在std查找endl并find它(在<iostream> )。

这里是编译器(C ++ 11模式)产生的结果 :

 prog.cpp: In function 'int main()': prog.cpp:4:36: error: 'endl' was not declared in this scope std::cout << "Hello, world" << endl; ^ 

这是编译器或书中的一个错误。 标准说什么?

更新:

我需要澄清一点。 我知道正确的答案是使用std::endl 。 问题是关于书中的文字。 正如Lachlan Easton所说,这不仅仅是一个错字。 整个段落(可能)是错误的。 我可以接受这种错误,如果这本书是由其他(不知名的)作者,但我是(现在仍然)怀疑,因为它是由Bjarne写的。

这不是编译器中的错误。 ADL用于查找函数而不是参数operator<<是通过查看参数std::cout和(应该是什么) std::endl通过ADLfind的函数。

对于那些说这是一个错字,事实并非如此。 Bjarne犯了一个错误,或者编译器错了。 OP发布的一段后面的段落是这样写的

没有依赖于参数的查找,endl操纵器将不会被发现。 实际上,编译器注意到<<的第一个参数是std中定义的一个ostream。 因此,它在std中查找endl并find它(在<iostream> )。

这是其他人已经指出的书中的一个错字。 但是,这本书的意思是 我们必须写

 std::operator<<(std::cout, "Hello, world").operator<<(std::endl); 

没有ADL。 这就是Bjarne冗长的意思。


我纠正了。 正如Lachlan Easton所指出的那样,这不是一个错字,而是一个错误 。 我无法访问这本书,这就是为什么我无法阅读这个段落并自己意识到这一点。 我已经把这个错误报告给了Bjarne,以便他能纠正它。


滑稽。 维基百科上也有同样的例子

请注意, std::endl是一个函数,但它需要充分的限定,因为它被用作operator<<std::endl是一个函数指针,而不是函数调用)的参数。

毫无疑问,这是书中的一个错误。 然而,例子std::operator<<(std::cout, "Hello, world").operator<<(std::endl); 显示AD​​L如何帮助减less冗长。


感谢gx_ 指出我的错误 。

提示的名称是“依赖于参数的查找”。

它是查找不合格的函数名称,这取决于 参数

这与查询争论没有任何关系。

Bjarne错过了。

我没有这本书,但是这似乎是本书中的一个错误,它缺less命名空间限定符的事实与ADL无关。 它应该是std::endl

是的,这是一个错误 – 这个例子是不合格的,不应该编译。 ADL适用于引入函数调用expression式的非限定函数名称。 endl是一个试图查找std::endl的idexpression式。 endl不会引入函数调用expression式,所以不使用依赖于参数的查找,只使用非限定查找,因此不会像预期的那样findstd::endl

一个更简单和正确的例子是:

 #include <vector> int main() { std::vector<int> x, y; swap(x,y); // calls std::swap due to ADL } 

总之,在查找具有不合格id(例如f )的函数调用(例如f(x,y,z) )之前,首先分析函数的参数(例如x,y,z )以确定它们的types。 关联的名称空间的列表是基于types形成的(例如,types定义的封闭名称空间是关联的名称空间)。 这些命名空间然后另外searchfunction。

Bjarne的例子的目的是炫耀std::operator<< function的ADL,而不是std::endl 。 这需要额外的理解,即重载操作符实际上是函数调用expression式,所以x << y表示operator<<(x,y) ,而operator<<是非限定名称,因此ADL适用于它。 LHS的types是std::ostream所以std是一个关联的命名空间,因此find了std::operator<<(ostream&, ...)

更正后的注释应为:

没有依赖于参数的查找, std命名空间中的重载的<<运算符将不会被find。 实际上,编译器注意到<<的第一个参数是std中定义的一个ostream。 因此,它在std中查找运算符<<并find它(在<iostream> )。