Bjarne 对这个 ADL 示例的看法是错误的,还是我有一个编译器错误
Is Bjarne wrong about this example of ADL, or do I have a compiler bug?
我正在阅读关于参数依赖查找的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
并找到它(在<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<<
是通过 ADL 通过查看参数 std::cout
和(应该是(std::endl
找到的函数。
对于那些说这是一个错字的人来说,事实并非如此。 要么是Bjarne犯了错误,要么是编译器错了。OP发布的段落之后的段落如下:
如果没有依赖于参数的查找,endl 操纵器就不会 发现。实际上,编译器注意到要<<的第一个参数是 在标准中定义的 ostream 。因此,它在 std 中查找 endl 和 找到它(在
<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 如何帮助减少详细程度。
感谢gx_指出我的错误。
提示在名称"依赖于参数的查找"中。
它是对非限定函数名称的查找,其工作取决于参数。
这与查找参数无关。
比亚恩说错了话。
这本书,但这似乎是书中的一个错误,它缺少命名空间限定符的事实与 ADL 无关。应该是std::endl
.
是的,这是一个错误 - 该示例格式不正确,不应编译。 ADL 适用于引入函数调用表达式的非限定函数名称。 endl
是尝试查找std::endl
的 id 表达式。 endl
没有引入函数调用表达式,因此不对它使用依赖于参数的查找,只使用非限定查找,因此它不会按预期找到std::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
(以确定其类型。 关联命名空间的列表基于类型形成(例如,类型定义的封闭命名空间是关联的命名空间(。 然后,还会在这些命名空间中搜索函数。
Bjarne的例子的目的是炫耀std::operator<<
函数的ADL,而不是std::endl
。 这需要进一步了解重载运算符实际上是函数调用表达式,因此x << y
表示operator<<(x,y)
,而operator<<
是一个非限定名,因此 ADL 适用于它。 LHS 的类型std::ostream
因此std
是关联的命名空间,因此可以找到std::operator<<(ostream&, ...)
。
更正后的附言应为:
如果没有依赖于参数的查找,则不会找到
std
命名空间中重载的<<
运算符。实际上,编译器注意到要<<的第一个参数是在 std 中定义的 ostream。因此,它在 std 中查找运算符<<
并找到它(在<iostream>
中(。
- VSCode-有一个红色下划线,但程序构建和运行正确,并且出现配音错误
- 我在 .h 中有一个枚举类,并且在.cpp错误中有一个运算符重载:与"运算符<<不匹配
- 我有一个线程 1:EXC_BAD_ACCESS(代码 = 1,地址 = 0x8)错误.我认为这是由于内存管理不好.我可以
- 处理程序的模块列表中有一个错误的模块"WebSocketModule"
- 编译器错误:函数调用在常量表达式中必须有一个常量值
- LNK2001尝试将我的主函数分离为主.cpp时,我有一个奇怪的错误
- 为什么有一个指向此代码行(第 7 行)的"no matching call for function"错误?
- 我在咖啡中添加了一个新层,但有一个关于"layer_param_"的错误
- 我在 c ++ 中有一个循环错误
- 为什么第三板有一个错误
- 我在代码中有一个错误,错误是:(智能感知:不允许抽象类类型"HourlyWorker"的对象:)
- 错误:在“(”标记之前进行预期的构造函数、析构函数或类型转换.即使我有一个构造函数
- 带有显式构造函数的智能指针使我有一个错误
- 我有一个与Irrlicht创建Cmakelist的错误
- 我的基本C 程序中有一个未指定的错误
- 它不是编译.我正在调用一个通过引用调用的函数,但有一个错误,无法将双*转换为双倍
- 得到错误"left of '.toString' must have class/struct/union",即使 toString 应该有一个合适的对象
- 我的调试器说我有一个隔离错误错误,但无法告诉我在哪里,在非常特殊的情况下发生
- 删除指向排序的字符串阵列的指针会在运行后会有一个错误
- 当我编译引用 std::ostream 时,我有一个奇怪的错误弹出