[basic.lookup.argdep]

# 6 Basics [[basic]](./#basic)

## 6.5 Name lookup [[basic.lookup]](basic.lookup#argdep)

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

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2100)

When the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") in
a function call ([[expr.call]](expr.call "7.6.1.3 Function call")) is an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]"),
and unqualified lookup ([[basic.lookup.unqual]](basic.lookup.unqual "6.5.3 Unqualified name lookup"))
for the name in the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") does not find any

- [(1.1)](#1.1)

declaration of a class member, or

- [(1.2)](#1.2)

function declaration inhabiting a block scope, or

- [(1.3)](#1.3)

declaration not of a function or function template

then lookup for the name also includes the result of[*argument-dependent lookup*](#def:lookup,argument-dependent "6.5.4 Argument-dependent name lookup [basic.lookup.argdep]") in a set of associated namespaces
that depends on the types of the arguments
(and for type template template arguments, the namespace of the template argument),
as specified below[.](#1.sentence-1)

[*Example [1](#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*]

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2133)

[*Note [1](#note-1)*:

For purposes of determining
(during parsing) whether an expression is a[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") for a function call, the usual name lookup
rules apply[.](#2.sentence-1)

In some cases
a name followed by < is treated as a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") even though name lookup did not find a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") (see [[temp.names]](temp.names "13.3 Names of template specializations"))[.](#2.sentence-2)

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 nameint y = g<N::A>(N::A()); // OK, lookup of g finds a function, g treated as template nameint z = h<N::A>(N::A()); // error: h< does not begin a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")

The rules have no effect on the syntactic interpretation of an expression[.](#2.sentence-4)

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[.](#2.sentence-6)

â *end note*]

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2178)

For each argument type T in the function call,
there is a set of zero or more [*associated entities*](#def:entity,associated "6.5.4 Argument-dependent name lookup [basic.lookup.argdep]") to be considered[.](#3.sentence-1)

The set of entities is determined entirely by
the types of the function arguments
(and any type template template arguments)[.](#3.sentence-2)

Any [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")*s* and [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*s* used to specify the types
do not contribute to this set[.](#3.sentence-3)

The set of entities
is determined in the following way:

- [(3.1)](#3.1)

  If T is std​::​meta​::​info ([[meta.syn]](meta.syn "21.4.1 Header <meta> synopsis")),
its associated set of entities is the singleton containing
the enumeration type std​::​meta​::​operators ([[meta.reflection.operators]](meta.reflection.operators "21.4.5 Operator representations"))[.](#3.1.sentence-1)
  [*Note [2](#note-2)*:
  The std​::​meta​::​info type is a type alias,
so an explicit rule is needed to associate calls
whose arguments are reflections with the namespace std​::​meta[.](#3.1.sentence-2)
 â *end note*]

- [(3.2)](#3.2)

  If T is any other fundamental type, its associated set of
entities is empty[.](#3.2.sentence-1)

- [(3.3)](#3.3)

  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, if it is a complete type, its direct and indirect base classes[.](#3.3.sentence-1)
  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 type template template arguments; and
the classes of which any member templates used as type template template
arguments are members[.](#3.3.sentence-2)
  [*Note [3](#note-3)*:
  Constant template arguments,
variable template template arguments, and
concept template arguments
do not
contribute to the set of associated entities[.](#3.3.sentence-3)
 â *end note*]

- [(3.4)](#3.4)

  If T is an enumeration type,
its associated entities are T and, if it is a class member, the member's class[.](#3.4.sentence-1)

- [(3.5)](#3.5)

  If T is a pointer to U or an array of U,
its associated entities are those associated with U[.](#3.5.sentence-1)

- [(3.6)](#3.6)

  If T is a function type, its associated
entities are those associated with the function parameter types and those
associated with the return type[.](#3.6.sentence-1)

- [(3.7)](#3.7)

  If T is a pointer to a member function of a classX, its associated entities are those associated
with the function parameter types and return type, together with those
associated with X[.](#3.7.sentence-1)

- [(3.8)](#3.8)

  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[.](#3.8.sentence-1)

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[.](#3.sentence-5)

Additionally, if the aforementioned overload set is named with
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"), its associated entities also include
its template template arguments and
those associated with its type template arguments[.](#3.sentence-6)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2254)

The [*associated namespaces*](#def: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]](namespace.def "9.9.2 Namespace definition"))
of those namespaces[.](#4.sentence-1)

Argument-dependent lookup finds
all declarations of functions and function templates that

- [(4.1)](#4.1)

are found by a search of any associated namespace, or

- [(4.2)](#4.2)

are declared as a friend ([[class.friend]](class.friend "11.8.4 Friends")) of any class
with a reachable definition in the set of associated entities, or

- [(4.3)](#4.3)

are exported,
are attached to a named module M ([[module.interface]](module.interface "10.2 Export declaration")),
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]](basic.link "6.7 Program and linkage"))[.](#4.sentence-2)

If the lookup is for a dependent name ([[temp.dep]](temp.dep "13.8.3 Dependent names"), [[temp.dep.candidate]](temp.dep.candidate "13.8.4.2 Candidate functions")),
the above lookup is also performed
from each point in the instantiation context ([[module.context]](module.context "10.6 Instantiation 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]](module.global.frag "10.4 Global module fragment")) or has internal linkage[.](#4.sentence-3)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2282)

[*Example [2](#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*]

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2324)

[*Note [4](#note-4)*:

The associated namespace can include namespaces
already considered by ordinary unqualified lookup[.](#6.sentence-1)

â *end note*]

[*Example [3](#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​::​fextern void g(NS::T, float);
 g(parm, 1); // OK, calls g(NS​::​T, float)} â *end example*]
