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 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), or
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.
A template argument is equivalent to a type template parameter
if it denotes the same type.
A template argument is equivalent to a constant 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
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 instantiationclass B {
B* p1; // B is the current instantiation
A<T>::B* p2; // A<T>::B is the current instantiationtypename 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 instantiationtypedef T1 my_T1;
staticconstint my_I = I;
staticconstint my_I2 = I+0;
staticconstint my_I3 = my_I;
staticconstlong my_I4 = I;
staticconstint 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 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 {typedefint M;
struct B {typedefvoid M;
struct C;
};
};
template<class T>struct A<T>::B::C : A<T>{
M m; // OK, A<T>::M};
— end example]
lookup for it finds any member of a class that is the current instantiation
[Example 3: template<class T>class A {staticconstint i =5;
int n1[i]; // i refers to a member of the current instantiationint n2[A::i]; // A::i refers to a member of the current instantiationint n3[A<T>::i]; // A<T>::i refers to a member of the current instantiationint 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.
its lookup context is the current instantiation and
has at least one dependent base class, and
qualified name lookup for the name finds nothing ([basic.lookup.qual]).
[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}templatevoid 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(){returnthis->m; }// finds A::m in the template definition contextint g(){return m; }// finds A::m in the template definition context};
templateint C<B>::f(); // error: finds both A::m and B::mtemplateint C<B>::g(); // OK, transformation to class member access syntax// does not occur in the template definition context; see [expr.prim.id.general] — end example]
it refers to an alias template
that is a member of the current instantiation and
whose defining-type-id is dependent after
class template argument deduction ([over.match.class.deduct])
and substitution ([temp.alias]).
denoted by a simple-template-id
in which either the template name is a template parameter or any of the
template arguments is dependent ([temp.dep.temp]),118
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.