CWG Issue 224 (original) (raw)
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, a name refers to the current instantiation if it is
- the injected-class-name (Clause 11 [class]) of the class template or nested class,
- in the definition of a primary class template, the name of the class template followed by the template argument list of the primary template (as described below) enclosed in <>,
- 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 partial specialization, the name of the class template followed by the template argument list of the partial specialization enclosed in <>.
The template argument list of a primary template is a template argument list in which the nth template argument has the value of the nth template parameter of the class template.
A template argument that is equivalent to a template parameter (i.e., has the same constant value or the same type as the template parameter) can be used in place of that template parameter in a reference to the current instantiation. In the case of a nontype template argument, the argument must have been given the value of the template parameter and not an expression involving the template parameter.
[Example:
template class A { A* p1; // A is the current instantiation A* p2; // A is the current instantiation A<T*> p3; // A<T*> is not the current instantiation ::A* p4; // ::A is the current instantiation class B { B* p1; // B is the current instantiation A::B* p2; // A::B is the current instantiation typename A<T*>::B* p3; // A<T*>::B is not the // current instantiation }; };
template class A<T*> { A<T*>* p1; // A<T*> is the current instantiation A* p2; // A 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; 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 };
—_end example_]
A name is a member of the current instantiation if it is
- An unqualified name that, when looked up, refers to a member of a class template. [Note: This can only occur when looking up a name in a scope enclosed by the definition of a class template.]
- A qualified-id in which the _nested-name-specifier_refers to the current instantiation.
[Example:
template 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::i]; // A::i refers to a member of the current instantiation int f(); };
template int A::f() { return i; // i refers to a member of the current instantiation }
—_end example_]
A name is a member of an unknown specialization if the name is a qualified-id in which the_nested-name-specifier_ names a dependent type that is not the current instantiation.
A type is dependent if it is
- a template parameter,
- a member of an unknown specialization,
- a nested class that is a member of 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 constructed from any dependent type or whose size is specified by a constant expression that is value-dependent, or
- a 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.
[Note: Because typedefs to 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.]