6 Basics [basic]

6.5 Name lookup [basic.lookup]

6.5.4 Argument-dependent name lookup [basic.lookup.argdep]

When the postfix-expression in a function call ([expr.call]) is an unqualified-id, and unqualified lookup ([basic.lookup.unqual]) for the name in the unqualified-id does not find any
  • declaration of a class member, or
  • function declaration inhabiting a block scope, or
  • declaration not of a function or function template
then lookup for the name also includes the result of argument-dependent lookup in a set of associated namespaces that depends on the types of the arguments (and for template template arguments, the namespace of the template argument), as specified below.
[Example 1: namespace N { struct S { }; void f(S); } void g() { N::S s; f(s); // OK: calls N​::​f (f)(s); // error: N​::​f not considered; parentheses prevent argument-dependent lookup } — end example]
[Note 1:
For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply.
In some cases a name followed by < is treated as a template-name even though name lookup did not find a template-name (see [temp.names]).
For example, int h; void g(); namespace N { struct A {}; template <class T> int f(T); template <class T> int g(T); template <class T> int h(T); } int x = f<N::A>(N::A()); // OK: lookup of f finds nothing, f treated as template name int y = g<N::A>(N::A()); // OK: lookup of g finds a function, g treated as template name int z = h<N::A>(N::A()); // error: h< does not begin a template-id
The rules have no effect on the syntactic interpretation of an expression.
For example, typedef int f; namespace N { struct A { friend void f(A &); operator int(); void g(A a) { int i = f(a); // f is the typedef, not the friend function: equivalent to int(a) } }; }
Because the expression is not a function call, argument-dependent name lookup does not apply and the friend function f is not found.
— end note]
For each argument type T in the function call, there is a set of zero or more associated entities to be considered.
The set of entities is determined entirely by the types of the function arguments (and any template template arguments).
Any typedef-names and using-declarations used to specify the types do not contribute to this set.
The set of entities is determined in the following way:
  • If T is a fundamental type, its associated set of entities is empty.
  • If T is a class type (including unions), its associated entities are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes.
    Furthermore, if T is a class template specialization, its associated entities also include: the entities associated with the types of the template arguments provided for template type parameters; the templates used as template template arguments; and the classes of which any member templates used as template template arguments are members.
    [Note 2:
    Non-type template arguments do not contribute to the set of associated entities.
    — end note]
  • If T is an enumeration type, its associated entities are T and, if it is a class member, the member's class.
  • If T is a pointer to U or an array of U, its associated entities are those associated with U.
  • If T is a function type, its associated entities are those associated with the function parameter types and those associated with the return type.
  • If T is a pointer to a member function of a class X, its associated entities are those associated with the function parameter types and return type, together with those associated with X.
  • If T is a pointer to a data member of class X, its associated entities are those associated with the member type together with those associated with X.
In addition, if the argument is an overload set or the address of such a set, its associated entities are the union of those associated with each of the members of the set, i.e., the entities associated with its parameter types and return type.
Additionally, if the aforementioned overload set is named with a template-id, its associated entities also include its template template-arguments and those associated with its type template-arguments.
The associated namespaces for a call are the innermost enclosing non-inline namespaces for its associated entities as well as every element of the inline namespace set ([namespace.def]) of those namespaces.
Argument-dependent lookup finds all declarations of functions and function templates that
  • are found by a search of any associated namespace, or
  • are declared as a friend ([class.friend]) of any class with a reachable definition in the set of associated entities, or
  • are exported, are attached to a named module M ([module.interface]), do not appear in the translation unit containing the point of the lookup, and have the same innermost enclosing non-inline namespace scope as a declaration of an associated entity attached to M ([basic.link]).
If the lookup is for a dependent name ([temp.dep], [temp.dep.candidate]), the above lookup is also performed from each point in the instantiation context ([module.context]) of the lookup, additionally ignoring any declaration that appears in another translation unit, is attached to the global module, and is either discarded ([module.global.frag]) or has internal linkage.
[Example 2:

Translation unit #1:export module M; namespace R { export struct X {}; export void f(X); } namespace S { export void f(R::X, R::X); }

Translation unit #2:export module N; import M; export R::X make(); namespace R { static int g(X); } export template<typename T, typename U> void apply(T t, U u) { f(t, u); g(t); }

Translation unit #3:module Q; import N; namespace S { struct Z { template<typename T> operator T(); }; } void test() { auto x = make(); // OK, decltype(x) is R​::​X in module M R::f(x); // error: R and R​::​f are not visible here f(x); // OK, calls R​::​f from interface of M f(x, S::Z()); // error: S​::​f in module M not considered // even though S is an associated namespace apply(x, S::Z()); // error: S​::​f is visible in instantiation context, but // R​::​g has internal linkage and cannot be used outside TU #2 } — end example]

[Note 3:
The associated namespace can include namespaces already considered by ordinary unqualified lookup.
— end note]
[Example 3: namespace NS { class T { }; void f(T); void g(T, int); } NS::T parm; void g(NS::T, float); int main() { f(parm); // OK: calls NS​::​f extern void g(NS::T, float); g(parm, 1); // OK: calls g(NS​::​T, float) } — end example]