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?)

3

There are 3 best solutions below

3
On

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.

4
On

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.

2
On

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.