19 KiB
[temp.res.general]
13 Templates [temp]
13.8 Name resolution [temp.res]
13.8.1 General [temp.res.general]
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.
If the name is dependent (as specified in [temp.dep]), it is looked up for each specialization (after substitution) because the lookup depends on a template parameter.
[Note 1:
Some dependent names are also looked up during parsing to determine that they are dependent or to interpret following < tokens.
Uses of other names might be type-dependent or value-dependent ([temp.dep.expr], [temp.dep.constexpr]).
A using-declarator is never dependent in a specialization and is therefore replaced during lookup for that specialization ([basic.lookup]).
â end note]
[Example 1: struct A { operator int(); };template<class B, class T>struct D : B { T get() { return operator T(); } // conversion-function-id is dependent};int f(D<A, int> d) { return d.get(); } // OK, lookup finds A::operator int â end example]
[Example 2: void f(char);
template 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: struct A {struct B { /* ... */ }; int a; int Y;};
int a;
template struct Y : T {struct B { /* ... / }; B b; // The B defined in Yvoid f(int i) { a = i; } // ::a Y p; // Y};
Y ya;
The members A::B, A::a, and A::Y of the template argument A do not affect the binding of names in Y.
â end example]
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]) but is not found by lookup for the specialization, the program is ill-formed, no diagnostic required.
typename-specifier:
typename nested-name-specifier identifier
typename nested-name-specifier templateopt simple-template-id
The component names of a typename-specifier are its identifier (if any) and those of its nested-name-specifier andsimple-template-id (if any).
A typename-specifier denotes the type or class template denoted by the simple-type-specifier ([dcl.type.simple]) formed by omitting the keyword typename.
[Note 2:
The usual qualified name lookup ([basic.lookup.qual]) applies even in the presence of typename.
â end note]
[Example 4: struct A {struct X { }; int X;};struct B {struct X { };};template 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]
A type-only context 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
atypename-specifier,type-requirement,nested-name-specifier,elaborated-type-specifier,class-or-decltype,using-enum-declarator, or
a simple-type-specifier of a friend-type-specifier, or
a type-specifier of a
default argument of a type-parameter, or
type-id of astatic_cast,const_cast,reinterpret_cast, ordynamic_cast, or
a decl-specifier of the decl-specifier-seq of a
simple-declaration or function-definition in namespace scope,
parameter-declaration in a member-declaration,116 unless that parameter-declaration appears in a default argument,
parameter-declaration in a declarator of a function or function template declaration whose declarator-id is qualified, unless that parameter-declaration appears in a default argument,
parameter-declaration in a lambda-declarator or requirement-parameter-list, unless that parameter-declaration appears in a default argument, or
parameter-declaration of a template-parameter (which necessarily declares a constant template parameter).
A splice-specifier orsplice-specialization-specifier ([basic.splice]) 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.
[Example 5: template T::R f(); // OK, return type of a function declaration at global scopetemplate void f(T::R); // ill-formed, no diagnostic required: attempt to declare// a void variable templateenum class Enum { A, B, C };template struct S {using Ptr = PtrTraits::Ptr; // OK, in a defining-type-idusing Alias = [:^^int:]; // OK, in a defining-type-id T::R f(T::P p) { // OK, class scopereturn static_cast<T::R>(p); // OK, type-id of a static_cast}auto g() -> S<T*>::Ptr; // OK, trailing-return-typeauto h() -> [:^^S:]<T*>; // OK, trailing-return-typeusing enum [:^^Enum:]; // OK, using-enum-declarator};template 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]
A qualified-id whose terminal name is dependent and that is in a type-only context is considered to denote a type.
A name that refers to a using-declarator whose terminal name is dependent is interpreted as a typedef-name if the using-declarator uses the keyword typename.
[Example 6: template 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(1); // OK f(1); // error: Foo::x is a type} â end example]
The validity of a templated entity may be checked prior to any instantiation.
[Note 3:
Knowing which names are type names allows the syntax of every template to be checked in this way.
â end note]
The program is ill-formed, no diagnostic required, if
no valid specialization, ignoring static_assert-declarations that fail ([dcl.pre]), can be generated for a templated entity or a substatement of a constexpr if statement ([stmt.if]) within a templated entity and the innermost enclosing template is not instantiated, or
no valid specialization, ignoring static_assert-declarations that fail, can be generated for the compound-statement of an expansion statement and there is no instantiation of it, or
no valid specialization, ignoring static_assert-declarations that fail, can be generated for a default template-argument and the default template-argument is not used in any instantiation, or
no specialization of an alias template ([temp.alias]) is valid and no specialization of the alias template is named in the program, or
any constraint-expression 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
every valid specialization of a variadic template requires an empty template parameter pack, or
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 that fails) that does not depend on a template parameter, or
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.
[Note 4:
This can happen in situations including the following:
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
lookup for a name in the template definition found a using-declaration, but the lookup in the corresponding scope in the instantiation does not find any declarations because the using-declaration was a pack expansion and the corresponding pack is empty, or
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
constant expression evaluation within the template instantiation uses
the value of a const object of integral or unscoped enumeration type or
the value of a constexpr object or
the value of a reference or
the definition of a constexpr function,
and that entity was not defined when the template was defined, or
a class template specialization or variable template specialization that is specified by a non-dependent simple-template-id 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.
â end note]
[Note 5:
If a template is instantiated, errors will be diagnosed according to the other rules in this document.
Exactly when these errors are diagnosed is a quality of implementation issue.
â end note]
[Example 7: int j;template 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::g(t); // OK X::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]
[Note 6:
For purposes of name lookup, default arguments andnoexcept-specifiers of function templates and default arguments and noexcept-specifiers of member functions of class templates are considered definitions ([temp.decls]).
â end note]
This includes friend function declarations.