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

狂风中的少年 提交于 2020-01-03 09:42:33

问题


I was looking at the Wikipedia entry on argument-dependent lookup, and (on Jan 04, 2014) the following example was given:

#include<iostream>

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

... with the following comment:

Note that std::endl is a function but it needs full qualification, since it is used as an argument to operator<< (std::endl is a function pointer, not a function call).

My thought is that the comment is incorrect (or simply unclear). I am considering changing the comment to say, instead

Note that std::endl needs full qualification, because ADL does not apply to the arguments of a function call; it only applies to the function name itself.

Am I correct that the Wikipedia comment is incorrect? Is my proposed change correct? (I.e., is my understanding of ADL correct in this example?)


回答1:


There's nothing wrong about what Wikipedia says.

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

is equivalent to the following (assuming operator<< is implemented as a free function)

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

which clearly requires namespace qualification for both cout and endl because this is argument-dependent lookup (of the function), not "argument lookup".
The arguments determine the function to be called, not the way around.




回答2:


Both the original phrasing and your phrasing are correct.

std::endl is a function. C++03 spec section 27.6 [lib.iostream.format]:

Header <ostream> synopsis

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);
...

In this context, the std::endl function (or more precisely, the function pointer into which it decays) is being passed as an argument to operator<<. Since it is an argument, ADL does not apply.




回答3:


The Wikipedia entry is correct. The fact that one of operator<<'s operands is in the std namespace causes name lookup to include declarations of operator<< from namespace std in the candidate-declarations set fed to overload resolution.



来源:https://stackoverflow.com/questions/20926217/why-does-stdendl-require-the-namespace-qualification-when-used-in-the-statem

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!