13 Templates [temp]

13.8 Name resolution [temp.res]

13.8.3 Dependent names [temp.dep]

13.8.3.1 General [temp.dep.general]

Inside a template, some constructs have semantics which may differ from one instantiation to another.
Such a construct depends on the template parameters.
In particular, types and expressions may depend on the type and/or value of template parameters (as determined by the template arguments) and this determines the context for name lookup for certain names.
An expression may be type-dependent (that is, its type may depend on a template parameter) or value-dependent (that is, its value when evaluated as a constant expression ([expr.const]) may depend on a template parameter) as described below.
A dependent call is an expression, possibly formed as a non-member candidate for an operator ([over.match.oper]), of the form: where the postfix-expression is an unqualified-id and
The component name of an unqualified-id ([expr.prim.id.unqual]) is dependent if
[Note 1: 
Such names are looked up only at the point of the template instantiation ([temp.point]) in both the context of the template definition and the context of the point of instantiation ([temp.dep.candidate]).
— end note]
[Example 1: template<class T> struct X : B<T> { typename T::A* pa; void f(B<T>* pb) { static int i = B<T>::i; pb->j++; } };
The base class name B<T>, the type name T​::​A, the names B<T>​::​i and pb->j explicitly depend on the template-parameter.
— end example]

13.8.3.2 Dependent types [temp.dep.type]

A name or template-id refers to the current instantiation if it is
  • in the definition of a class template, a nested class of a class template, a member of a class template, or a member of a nested class of a class template, the injected-class-name of the class template or nested class,
  • in the definition of a primary class template or a member of a primary class template, the name of the class template followed by the template argument list of its template-head ([temp.arg]) enclosed in <> (or an equivalent template alias specialization),
  • in the definition of a nested class of a class template, the name of the nested class referenced as a member of the current instantiation, or
  • in the definition of a class template partial specialization or a member of a class template partial specialization, the name of the class template followed by a template argument list equivalent to that of the partial specialization ([temp.spec.partial]) enclosed in <> (or an equivalent template alias specialization).
A template argument that is equivalent to a template parameter can be used in place of that template parameter in a reference to the current instantiation.
For a template type-parameter, a template argument is equivalent to a template parameter if it denotes the same type.
For a non-type template parameter, a template argument is equivalent to a template parameter if it is an identifier that names a variable that is equivalent to the template parameter.
A variable is equivalent to a template parameter if
  • it has the same type as the template parameter (ignoring cv-qualification) and
  • its initializer consists of a single identifier that names the template parameter or, recursively, such a variable.
[Note 1: 
Using a parenthesized variable name breaks the equivalence.
— end note]
[Example 1: template <class T> class A { A* p1; // A is the current instantiation A<T>* p2; // A<T> is the current instantiation A<T*> p3; // A<T*> is not the current instantiation ::A<T>* p4; // ​::​A<T> is the current instantiation class B { B* p1; // B is the current instantiation A<T>::B* p2; // A<T>​::​B is the current instantiation typename A<T*>::B* p3; // A<T*>​::​B is not the current instantiation }; }; template <class T> class A<T*> { A<T*>* p1; // A<T*> is the current instantiation A<T>* p2; // A<T> is not the current instantiation }; template <class T1, class T2, int I> struct B { B<T1, T2, I>* b1; // refers to the current instantiation B<T2, T1, I>* b2; // not the current instantiation typedef T1 my_T1; static const int my_I = I; static const int my_I2 = I+0; static const int my_I3 = my_I; static const long my_I4 = I; static const int my_I5 = (I); B<my_T1, T2, my_I>* b3; // refers to the current instantiation B<my_T1, T2, my_I2>* b4; // not the current instantiation B<my_T1, T2, my_I3>* b5; // refers to the current instantiation B<my_T1, T2, my_I4>* b6; // not the current instantiation B<my_T1, T2, my_I5>* b7; // not the current instantiation }; — end example]
A dependent base class is a base class that is a dependent type and is not the current instantiation.
[Note 2: 
A base class can be the current instantiation in the case of a nested class naming an enclosing class as a base.
[Example 2: template<class T> struct A { typedef int M; struct B { typedef void M; struct C; }; }; template<class T> struct A<T>::B::C : A<T> { M m; // OK, A<T>​::​M }; — end example]
— end note]
A qualified ([basic.lookup.qual]) or unqualified name is a member of the current instantiation if
  • its lookup context, if it is a qualified name, is the current instantiation, and
  • lookup for it finds any member of a class that is the current instantiation
[Example 3: template <class T> class A { static const int i = 5; int n1[i]; // i refers to a member of the current instantiation int n2[A::i]; // A​::​i refers to a member of the current instantiation int n3[A<T>::i]; // A<T>​::​i refers to a member of the current instantiation int f(); }; template <class T> int A<T>::f() { return i; // i refers to a member of the current instantiation } — end example]
A qualified or unqualified name names a dependent member of the current instantiation if it is a member of the current instantiation that, when looked up, refers to at least one member declaration (including a using-declarator whose terminal name is dependent) of a class that is the current instantiation.
A qualified name ([basic.lookup.qual]) is dependent if
[Example 4: struct A { using B = int; A f(); }; struct C : A {}; template<class T> void g(T t) { decltype(t.A::f())::B i; // error: typename needed to interpret B as a type } template void g(C); // …even though A is ​::​A here — end example]
If, for a given set of template arguments, a specialization of a template is instantiated that refers to a member of the current instantiation with a qualified name, the name is looked up in the template instantiation context.
If the result of this lookup differs from the result of name lookup in the template definition context, name lookup is ambiguous.
[Example 5: struct A { int m; }; struct B { int m; }; template<typename T> struct C : A, T { int f() { return this->m; } // finds A​::​m in the template definition context int g() { return m; } // finds A​::​m in the template definition context }; template int C<B>::f(); // error: finds both A​::​m and B​::​m template int C<B>::g(); // OK, transformation to class member access syntax // does not occur in the template definition context; see [class.mfct.non.static] — end example]
A type is dependent if it is
  • a template parameter,
  • denoted by a dependent (qualified) name,
  • a nested class or enumeration that is a direct member of a class that is the current instantiation,
  • a cv-qualified type where the cv-unqualified type is dependent,
  • a compound type constructed from any dependent type,
  • an array type whose element type is dependent or whose bound (if any) is value-dependent,
  • a function type whose parameters include one or more function parameter packs,
  • a function type whose exception specification is value-dependent,
  • denoted by a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent or is a pack expansion,126 or
  • denoted by decltype(expression), where expression is type-dependent.
[Note 3: 
Because typedefs do not introduce new types, but instead simply refer to other types, a name that refers to a typedef that is a member of the current instantiation is dependent only if the type referred to is dependent.
— end note]
125)125)
Every instantiation of a class template declares a different set of assignment operators.
126)126)
This includes an injected-class-name ([class.pre]) of a class template used without a template-argument-list.

13.8.3.3 Type-dependent expressions [temp.dep.expr]

Except as described below, an expression is type-dependent if any subexpression is type-dependent.
this is type-dependent if the current class ([expr.prim.this]) is dependent ([temp.dep.type]).
An id-expression is type-dependent if it is a template-id that is not a concept-id and is dependent; or if its terminal name is or if it names a dependent member of the current instantiation that is a static data member of type “array of unknown bound of T” for some T ([temp.static]).
Expressions of the following forms are type-dependent only if the type specified by the type-id, simple-type-specifier, typename-specifier, or new-type-id is dependent, even if any subexpression is type-dependent:
Expressions of the following forms are never type-dependent (because the type of the expression cannot be dependent):
literal
sizeof unary-expression
sizeof ( type-id )
sizeof ... ( identifier )
alignof ( type-id )
typeid ( expression )
typeid ( type-id )
:: delete cast-expression
:: delete [ ] cast-expression
throw assignment-expression
noexcept ( expression )
[Note 1: 
For the standard library macro offsetof, see [support.types].
— end note]
A class member access expression is type-dependent if the terminal name of its id-expression, if any, is dependent or the expression refers to a member of the current instantiation and the type of the referenced member is dependent.
[Note 2: 
In an expression of the form x.y or xp->y the type of the expression is usually the type of the member y of the class of x (or the class pointed to by xp).
However, if x or xp refers to a dependent type that is not the current instantiation, the type of y is always dependent.
— end note]
A braced-init-list is type-dependent if any element is type-dependent or is a pack expansion.
A fold-expression is type-dependent.

13.8.3.4 Value-dependent expressions [temp.dep.constexpr]

Except as described below, an expression used in a context where a constant expression is required is value-dependent if any subexpression is value-dependent.
An id-expression is value-dependent if:
  • it is a concept-id and any of its arguments are dependent,
  • it is type-dependent,
  • it is the name of a non-type template parameter,
  • it names a static data member that is a dependent member of the current instantiation and is not initialized in a member-declarator,
  • it names a static member function that is a dependent member of the current instantiation, or
  • it names a potentially-constant variable ([expr.const]) that is initialized with an expression that is value-dependent.
Expressions of the following form are value-dependent if the unary-expression or expression is type-dependent or the type-id is dependent:
sizeof unary-expression
sizeof ( type-id )
typeid ( expression )
typeid ( type-id )
alignof ( type-id )
noexcept ( expression )
[Note 1: 
For the standard library macro offsetof, see [support.types].
— end note]
Expressions of the following form are value-dependent if either the type-id or simple-type-specifier is dependent or the expression or cast-expression is value-dependent:
simple-type-specifier ( expression-list )
static_cast < type-id > ( expression )
const_cast < type-id > ( expression )
reinterpret_cast < type-id > ( expression )
( type-id ) cast-expression
Expressions of the following form are value-dependent:
sizeof ... ( identifier )
fold-expression
An expression of the form &qualified-id where the qualified-id names a dependent member of the current instantiation is value-dependent.
An expression of the form &cast-expression is also value-dependent if evaluating cast-expression as a core constant expression succeeds and the result of the evaluation refers to a templated entity that is an object with static or thread storage duration or a member function.

13.8.3.5 Dependent template arguments [temp.dep.temp]

A type template-argument is dependent if the type it specifies is dependent.
A non-type template-argument is dependent if its type is dependent or the constant expression it specifies is value-dependent.
Furthermore, a non-type template-argument is dependent if the corresponding non-type template-parameter is of reference or pointer type and the template-argument designates or points to a member of the current instantiation or a member of a dependent type.
A template template-parameter is dependent if it names a template-parameter or its terminal name is dependent.