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);
显示ADL如何帮助减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>
)。