7

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

Dan Nissenbaum
  • 13,558
  • 21
  • 105
  • 181
  • Same reason why `cout` needs namespace qualification. – user541686 Jan 04 '14 at 20:19
  • @Mehrdad Although, conceivably, if ADL **were** used to lookup names used as *other arguments* to the function, the name could be found using ADL. – Dan Nissenbaum Jan 04 '14 at 20:20
  • ADL means that the name of the function can be inferred from the arguments, not the other way round. – Kerrek SB Jan 04 '14 at 20:22
  • @KerrekSB There is a third potential case - that the name of *other* arguments can be inferred from *some* argument. I (think I) know that this is *not* how ADL works; hence my suggested edit to the Wikipedia article. – Dan Nissenbaum Jan 04 '14 at 20:25
  • @DanNissenbaum: Why would you think that? [basic.lookup.argdep] is pretty clear I think: "other namespaces [for the name of the *postfix-expression*...] may be searched [...] These modifications to the search depend on the types of the arguments". – Kerrek SB Jan 04 '14 at 20:29
  • @KerrekSB Perhaps this needs to be another question, but is it *true* that `namespace Foo { class A{}; class B{}; void f(A, B){} }` followed by `Foo::A a; f(a, B());` will correctly locate the name `B`? (This would be ADL successfully locating the type of an argument to a function call within a namespace, given another argument to the same function whose type is known to be defined in that namespace - if I understand this correctly.) – Dan Nissenbaum Jan 04 '14 at 20:34

3 Answers3

10

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.

user541686
  • 205,094
  • 128
  • 528
  • 886
  • Good point. The nestedness, when spelled out, makes clear that the `std::endl` is the **only** argument in `namespace std` for the *first* call to `operator<<`, and hence it is necessary to trigger ADL. However: isn't it then true that the comment, appearing in Wikipedia, *(std::endl is a function pointer, not a function call)*, is irrelevant (and therefore misleading)? – Dan Nissenbaum Jan 04 '14 at 20:30
  • @DanNissenbaum: I suppose I could agree it's slightly misleading, because if there was a `std::get_endl()` function that returned `std::endl` it would be a function call, but that would be irrelevant to the whole ADL issue. It's kind of a roundabout way to think about it so it's not common to interpret it that way but if you do I guess it is confusing. What you said certainly isn't wrong so maybe go ahead and change it? – user541686 Jan 04 '14 at 20:33
  • @DanNissenbaum: I think what Wikipedia meant to do is to *counter* the possible argument, *"But `endl(std::cout)` doesn't require namespace qualification!"*, to which the answer is *"`endl` here is a function call, not a function pointer"*. It makes sense in that context, but if you read it literally I can see why it would be misleading. – user541686 Jan 04 '14 at 20:36
3

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.

Nemo
  • 70,042
  • 10
  • 116
  • 153
  • If so, I think that the statement, in Wikipedia, `(std::endl is a function pointer, not a function call)`, is irrelevant to ADL and hence misleading. I'd like to remove it. – Dan Nissenbaum Jan 04 '14 at 20:40
  • It is not technically wrong... But I agree it seems like irrelevant, and potentially misleading, detail. So I would say go for it. – Nemo Jan 04 '14 at 21:11
1

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.

jthill
  • 55,082
  • 5
  • 77
  • 137
  • Note that I am asking not about the lookup of the *function declaration*, but instead the lookup of *another argument* to the function. In other words, because *at least one* argument is in `namespace std`, conceivably ADL could be used to look into that namespace to locate *other* arguments to the same function. – Dan Nissenbaum Jan 04 '14 at 20:23
  • @DanNissenbaum That would be ~function-dependent lookup~ for argument names, not argument-dependent lookup for function names. – jthill Jan 04 '14 at 20:31
  • Therefore, I'd think my suggested change is correct - according to this reasoning. Perhaps I don't understand. – Dan Nissenbaum Jan 04 '14 at 20:38
  • @DanNissenbaum I think both your changed version and the wikipedia version are correct. If I were after improving it I'd say what I said above, that the namespaces of all supplied arguments are searched for overload candidates (and perhaps add that since no arguments are supplied for `endl`, it needs a qualification or `using`). – jthill Jan 04 '14 at 21:22