[temp.res.general]

# 13 Templates [[temp]](./#temp)

## 13.8 Name resolution [[temp.res]](temp.res#general)

### 13.8.1 General [temp.res.general]

[1](#1)

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

A name that appears in a declaration D of a template T is looked up
from where it appears
in an unspecified declaration of T that either is D itself or is reachable from D and
from which no other declaration of T that contains the usage of the name is reachable[.](#1.sentence-1)

If the name is dependent (as specified in [[temp.dep]](temp.dep "13.8.3 Dependent names")),
it is looked up for each specialization (after substitution)
because the lookup depends on a template parameter[.](#1.sentence-2)

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

Some dependent names are also looked up during parsing to determine
that they are dependent or to interpret following < tokens[.](#1.sentence-3)

Uses of other names might be type-dependent or
value-dependent ([[temp.dep.expr]](temp.dep.expr "13.8.3.3 Type-dependent expressions"), [[temp.dep.constexpr]](temp.dep.constexpr "13.8.3.4 Value-dependent expressions"))[.](#1.sentence-4)

A [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") is never dependent in a specialization and
is therefore replaced during lookup for that specialization ([[basic.lookup]](basic.lookup "6.5 Name lookup"))[.](#1.sentence-5)

â *end note*]

[*Example [1](#example-1)*: struct A { operator int(); };template<class B, class T>struct D : B { T get() { return operator T(); } // [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") is dependent};int f(D<A, int> d) { return d.get(); } // OK, lookup finds A​::​operator int â *end example*]

[*Example [2](#example-2)*: void f(char);

template<class T> void g(T t) { f(1); // f(char) f(T(1)); // dependent f(t); // dependent dd++; // not dependent; error: declaration for dd not found}enum E { e };void f(E);

double dd;void h() { g(e); // will cause one call of f(char) followed by two calls of f(E) g('a'); // will cause three calls of f(char)} â *end example*]

[*Example [3](#example-3)*: struct A {struct B { /* ... */ }; int a; int Y;};

int a;

template<class T> struct Y : T {struct B { /* ... */ };
 B b; // The B defined in Yvoid f(int i) { a = i; } // ​::​a Y* p; // Y<T>};

Y<A> ya;

The members A​::​B, A​::​a, and A​::​Y of the template argument A do not affect the binding of names in Y<A>[.](#1.sentence-6)

â *end example*]

[2](#2)

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

If the validity or meaning of the program would be changed by
considering a default argument or default template argument
introduced in a declaration that is reachable from
the point of instantiation of a specialization ([[temp.point]](temp.point "13.8.4.1 Point of instantiation"))
but is not found by lookup for the specialization,
the program is ill-formed, no diagnostic required[.](#2.sentence-1)

[typename-specifier:](#nt:typename-specifier "13.8.1 General [temp.res.general]")  
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")  
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")

[3](#3)

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

The component names of a [*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]") are
its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") (if any) and
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") (if any)[.](#3.sentence-1)

A [*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]") denotes the type or class template
denoted by the [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") ([[dcl.type.simple]](dcl.type.simple "9.2.9.3 Simple type specifiers"))
formed by omitting the keyword typename[.](#3.sentence-2)

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

The usual qualified name lookup ([[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup")) applies
even in the presence of typename[.](#3.sentence-3)

â *end note*]

[*Example [4](#example-4)*: struct A {struct X { }; int X;};struct B {struct X { };};template<class T> void f(T t) {typename T::X x;}void foo() { A a;
 B b;
 f(b); // OK, T​::​X refers to B​::​X f(a); // error: T​::​X refers to the data member A​::​X not the struct A​::​X} â *end example*]

[4](#4)

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

A [*type-only context*](#def:context,type-only "13.8.1 General [temp.res.general]") is defined as follows:
A qualified or unqualified name is said to be in
a type-only context if it is the terminal name of

- [(4.1)](#4.1)

a[*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]"),[*type-requirement*](expr.prim.req.type#nt:type-requirement "7.5.8.3 Type requirements [expr.prim.req.type]"),[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"),[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1 General [class.derived.general]"),[*using-enum-declarator*](enum.udecl#nt:using-enum-declarator "9.8.2 The using enum declaration [enum.udecl]"),
or

- [(4.2)](#4.2)

a [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") of a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1 General [class.mem.general]"), or

- [(4.3)](#4.3)

a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") of a
  * [(4.3.1)](#4.3.1)

[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]"),

  * [(4.3.2)](#4.3.2)

[*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]"),

  * [(4.3.3)](#4.3.3)

[*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]"),

  * [(4.3.4)](#4.3.4)

[*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]"),

  * [(4.3.5)](#4.3.5)

default argument of a [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]"), or

  * [(4.3.6)](#4.3.6)

[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of astatic_cast,const_cast,reinterpret_cast, ordynamic_cast, or

- [(4.4)](#4.4)

a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of a
  * [(4.4.1)](#4.4.1)

[*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [dcl.pre]") or [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]") in namespace scope,

  * [(4.4.2)](#4.4.2)

[*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]"),

  * [(4.4.3)](#4.4.3)

[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]"),[116](#footnote-116 "This includes friend function declarations.") unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appears in a default argument,

  * [(4.4.4)](#4.4.4)

[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") in a [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") of a function or function template declaration
whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is qualified,
unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appears in a default argument,

  * [(4.4.5)](#4.4.5)

[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") in a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") or [*requirement-parameter-list*](expr.prim.req.general#nt:requirement-parameter-list "7.5.8.1 General [expr.prim.req.general]"),
unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appears in a default argument, or

  * [(4.4.6)](#4.4.6)

[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") of a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") (which necessarily declares a constant template parameter)[.](#4.sentence-1)

A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") ([[basic.splice]](basic.splice "6.6 Splice specifiers"))
is said to be in a type-only context
if a hypothetical qualified name appearing in the same position
would be in a type-only context[.](#4.sentence-2)

[*Example [5](#example-5)*: template<class T> T::R f(); // OK, return type of a function declaration at global scopetemplate<class T> void f(T::R); // ill-formed, no diagnostic required: attempt to declare// a void variable templateenum class Enum { A, B, C };template<class T> struct S {using Ptr = PtrTraits<T>::Ptr; // OK, in a [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]")using Alias = [:^^int:]; // OK, in a [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]") T::R f(T::P p) { // OK, class scopereturn static_cast<T::R>(p); // OK, [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a static_cast}auto g() -> S<T*>::Ptr; // OK, [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")auto h() -> [:^^S:]<T*>; // OK, [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")using enum [:^^Enum:]; // OK, [*using-enum-declarator*](enum.udecl#nt:using-enum-declarator "9.8.2 The using enum declaration [enum.udecl]")};template<typename T> void f() {void (*pf)(T::X); // variable pf of type void* initialized with T​::​Xvoid g(T::X); // error: T​::​X at block scope does not denote a type// (attempt to declare a void variable)} â *end example*]

[5](#5)

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

A [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") whose terminal name is dependent and that is in a type-only context
is considered to denote a type[.](#5.sentence-1)

A name
that refers to a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") whose terminal name is dependent
is interpreted as a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") if the [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") uses the keyword typename[.](#5.sentence-2)

[*Example [6](#example-6)*: template <class T> void f(int i) { T::x * i; // expression, not the declaration of a variable i}struct Foo {typedef int x;};

struct Bar {static int const x = 5;};

int main() { f<Bar>(1); // OK f<Foo>(1); // error: Foo​::​x is a type} â *end example*]

[6](#6)

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

The validity of a templated entity may be checked prior to any instantiation[.](#6.sentence-1)

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

Knowing which names are type names allows the syntax of every template
to be checked in this way[.](#6.sentence-2)

â *end note*]

The program is ill-formed, no diagnostic required, if

- [(6.1)](#6.1)

no valid specialization,
ignoring [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]")s that fail ([[dcl.pre]](dcl.pre "9.1 Preamble")),
can be generated for a templated entity
or a substatement of a constexpr if statement ([[stmt.if]](stmt.if "8.5.2 The if statement"))
within a templated entity
and the innermost enclosing template is not instantiated, or

- [(6.2)](#6.2)

no valid specialization,
ignoring [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]")s that fail,
can be generated for the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of an expansion statement and there is no instantiation of it, or

- [(6.3)](#6.3)

no valid specialization,
ignoring [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]")s that fail,
can be generated for a default [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") and
the default [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") is not used in any instantiation, or

- [(6.4)](#6.4)

no specialization of an alias template ([[temp.alias]](temp.alias "13.7.8 Alias templates")) is valid and
no specialization of the alias template is named in the program, or

- [(6.5)](#6.5)

any [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") in the program, introduced or otherwise,
has (in its normal form) an atomic constraint A where
no satisfaction check of A could be well-formed and
no satisfaction check of A is performed, or

- [(6.6)](#6.6)

every valid specialization of a variadic template requires an empty template
parameter pack, or

- [(6.7)](#6.7)

a hypothetical instantiation of a templated entity
immediately following its definition
would be ill-formed
due to a construct
(other than a [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]") that fails)
that does not depend on a template parameter, or

- [(6.8)](#6.8)

the interpretation of such a construct
in the hypothetical instantiation
is different from
the interpretation of the corresponding construct
in any actual instantiation of the templated entity[.](#6.sentence-3)

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

This can happen in situations including the following:

- [(6.9)](#6.9)

a type used in a non-dependent name is incomplete at the point at which a
template is defined but is complete at the point at which an instantiation is
performed, or

- [(6.10)](#6.10)

lookup for a name in the template definition found a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]"),
but the lookup in the corresponding scope in the instantiation
does not find any declarations because the [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") was a pack expansion and the corresponding pack is empty, or

- [(6.11)](#6.11)

an instantiation uses a default argument or default template argument
that had not been defined at the point at which the template was defined, or

- [(6.12)](#6.12)

[constant expression evaluation](expr.const "7.7 Constant expressions [expr.const]") within the template
instantiation uses
  * [(6.12.1)](#6.12.1)

the value of a const object of integral or unscoped enumeration type or

  * [(6.12.2)](#6.12.2)

the value of a constexpr object or

  * [(6.12.3)](#6.12.3)

the value of a reference or

  * [(6.12.4)](#6.12.4)

the definition of a constexpr function,

and that entity was not defined when the template was defined, or

- [(6.13)](#6.13)

a class template specialization or variable template specialization that
is specified by a non-dependent [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") is used by
the template, and either it is instantiated from a partial specialization that
was not defined when the template was defined or it names an explicit
specialization that was not declared when the template was defined[.](#6.sentence-4)

â *end note*]

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

If a template is instantiated, errors will be diagnosed according
to the other rules in this document[.](#6.sentence-5)

Exactly when these errors are diagnosed is a quality of implementation issue[.](#6.sentence-6)

â *end note*]

[*Example [7](#example-7)*: int j;template<class T> class X {void f(T t, int i, char* p) { t = i; // diagnosed if X​::​f is instantiated, and the assignment to t is an error p = i; // may be diagnosed even if X​::​f is not instantiated p = j; // may be diagnosed even if X​::​f is not instantiated X<T>::g(t); // OK X<T>::h(); // may be diagnosed even if X​::​f is not instantiated}void g(T t) {+; // may be diagnosed even if X​::​g is not instantiated}};

template<class... T> struct A {void operator++(int, T... t); // error: too many parameters};template<class... T> union X : T... { }; // error: union with base classtemplate<class... T> struct A : T..., T... { }; // error: duplicate base class â *end example*]

[7](#7)

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

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

For purposes of name lookup, default arguments and[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")*s* of function templates and default
arguments and [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")*s* of
member functions of class templates are considered definitions ([[temp.decls]](temp.decls "13.7 Template declarations"))[.](#7.sentence-1)

â *end note*]

[116)](#footnote-116)[116)](#footnoteref-116)

This includes friend function declarations[.](#footnote-116.sentence-1)
