Explaining unqualified lookup in templates


With reference to http://clang.llvm.org/compatibility.html#dep_lookup:
I've just run into exactly the problem with overloaded operator<< that
this page describes. I've modified my code as suggested, but out of
interest I'm curious as to why the unqualified lookup on dependent
names is done immediately rather than deferred until template
instantiation (when the argument-dependent lookup is done). It seems
to contradict the C++11 spec 14.6.2 (it looks like C++98 has the same
language as well), which says:

"If an operand of an operator is a type-dependent expression, the
operator also denotes a dependent name. Such names are unbound and are
looked up at the point of the template instantiation ( in
both the context of the template definition and the context of the
point of instantiation."

In the example at the URL above, std::cout<<value has a second
argument which is type-dependent, so I would expect operator<< to be
looked up in the context of the point of instantiation, at which point
the appropriate overload is defined.


Ah, this one is amusing.

Actually, overload resolution is done at the point of instantiation.

However, for the template code to be valid, the name should exist at the point where the template is declared…

In the URL mentionned, you could perfectly declare:

struct Useless; Useless Multiply(Useless, Useless);

Prior to the template and it would suffice to appease the compiler. No definition of either Useless or its Multiply would be needed because they will not be used in the end.

I sometimes wonder if this was done to “secure” the template instantiation by guaranteeing that at least one overload exist (even if not suitable, we cannot know at this point), rather than say… an object of that name.

– Matthieu

The text you've quoted is rather imprecise about exactly what kinds of lookups are performed at each time.The lookup in the context of the template definition is unqualified name lookup + argument-dependent name lookup. The lookup in the context of the point of instantiation is only argument-dependent lookup.

  - Doug

Notionally, yes, name lookup occurs at the point of instantiation. But that doesn’t mean that name lookup finds names which have been declared since the template was defined. The relevant section is

“For a function call that depends on a template parameter, the candidate functions are found using the usual
lookup rules (3.4.1, 3.4.2, 3.4.3) except that:
— For the part of the lookup using unqualified name lookup (3.4.1) or qualified name lookup (3.4.3), only
function declarations from the template definition context are found.
— For the part of the lookup using associated namespaces (3.4.2), only function declarations found in
either the template definition context or the template instantiation context are found.”

Thanks, that's the piece of the puzzle I was missing.