为什么在语句"std::cout << std::endl;"中使用时需要命名空间限定,给定依赖于参数的查找?

Why does 'std::endl' require the namespace qualification when used in the statement 'std::cout << std::endl;", given argument-dependent lookup?

本文关键字:lt std 参数 命名空间 查找 依赖于 endl cout 语句 为什么      更新时间:2023-10-16

我正在查看维基百科关于参数依赖查找的条目,并且(2014年1月4日)给出了以下示例:

#include<iostream>
int main() 
{
  std::cout << "Hello World, where did operator<<() come from?" << std::endl;
}

。并附有以下评论:

请注意,std::endl 是一个函数,但它需要完全限定, 因为它用作运算符的参数<<(std::endl 是一个函数 指针,而不是函数调用)。

我的想法是评论不正确(或根本不清楚)。 我正在考虑将评论更改为说,而不是

请注意,std::endl 需要完全限定, 因为 ADL 不适用于函数调用的参数;它 仅适用于函数名称本身。

我是否正确,维基百科的评论不正确? 我提议的更改是否正确? (即,在这个例子中,我对ADL的理解是否正确?

维基百科所说的没有错。

std::cout << "Hello World, where did operator<<() come from?" << std::endl

等效于以下内容(假设operator<<是作为自由函数实现的)

operator<<(
    operator<<(std::cout, "Hello World, where did operator<<() come from?"),
    std::endl)

这显然需要对coutendl进行命名空间限定,因为这是(函数的)依赖于参数的查找,而不是"参数查找"。
参数确定要调用的函数,而不是方法。

原始措辞和您的措辞都是正确的。

std::endl是一个函数。C++03 规范第 27.6 节 [lib.iostream.format]:

标题<ostream>概要

namespace std {
template <class charT, class traits = char_traits<charT> >
class basic_ostream;
typedef basic_ostream<char> ostream;
typedef basic_ostream<wchar_t> wostream;
template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);
...

在此上下文中,std::endl函数(或者更准确地说,它衰减到的函数指针)作为参数传递给operator<<。由于它是一个参数,ADL 不适用。

维基百科条目是正确的。 operator<< 的操作数之一位于 std 命名空间中的事实导致名称查找包含来自命名空间stdoperator<<声明,这些声明包含在设置为重载解析的候选声明中。