This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-12-20
[Moved to DR at 10/01 meeting.]
The definition of when a type is dependent, given in13.8.3.2 [temp.dep.type], is essentially syntactic: if thereference is aqualified-id and one of theclass-namesin thenested-name-specifier is dependent, the type isdependent. This approach leads to surprising results:
template <class T> class X { typedef int I;I a; // non-dependent typename X<T>::I b; // dependent typename X::I c; // dependent (X is equivalent to X<T>) };Suggested resolution:
The decision on whether a name is dependent or non-dependent shouldbe based on lookup, not on the form of the name: if the name can belooked up in the definition context and cannot be anything else as theresult of specialization, the name should be non-dependent.
See papers J16/00-0028 = WG21 N1251 andJ16/00-0056 = WG21 N1279.
Proposed resolution (10/00):
Replace section 13.8.3.2 [temp.dep.type] with thefollowing:
In the definition of a class template, a nested class of a classtemplate, a member of a class template, or a member of a nested classof a class template, a name refers to thecurrentinstantiation if it is
- the injected-class-name (Clause 11 [class]) of theclass template or nested class,
- in the definition of a primary class template, the name of theclass template followed by the template argument list of theprimary 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 thecurrent instantiation, or
- in the definition of a partial specialization, the name ofthe class template followed by the template argument list ofthe partial specialization enclosed in <>.
The template argument list of a primary template is atemplate argument list in which the nth templateargument has the value of the nth templateparameter of the class template.
A template argument that is equivalent to a templateparameter (i.e., has the same constant value or the same typeas the template parameter) can be used in place of thattemplate parameter in a reference to the currentinstantiation. In the case of a nontype template argument,the argument must have been given the value of thetemplate parameter and not an expression involving thetemplate parameter.
[Example:
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 instantiationA<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 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 amember of the current instantiation if it is
- An unqualified name that, when looked up, refers to a memberof a class template. [Note: This can only occur whenlooking up a name in a scope enclosed by the definition of aclass template.]
- Aqualified-id in which thenested-name-specifierrefers to the current instantiation.
[Example:
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 name is amember of an unknown specialization if thename is aqualified-id in which thenested-name-specifier names a dependent type that is notthe 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 currentinstantiation,
- 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 whosesize is specified by a constant expression that is value-dependent, or
- atemplate-id in which either the template name is atemplate parameter or any of the template arguments is a dependenttype or an expression that is type-dependent or value-dependent.
[Note: Because typedefs to not introduce new types, butinstead simply refer to other types, a name that refers to atypedef that is a member of the current instantiation is dependentonly if the type referred to is dependent.]
In 13.8.3.3 [temp.dep.expr] paragraph 3, replace
- anested-name-specifier that contains aclass-name that names a dependent type.
with
- anested-name-specifier orqualified-id thatnames a member of an unknown specialization.
In 13.8.3.3 [temp.dep.expr], add the followingparagraph:
A class member access expression (7.6.1.5 [expr.ref]) istype-dependent if the type of the referenced member is dependent.[Note: In an expression of the formx.y orxp->y the type of the expression is usually the typeof the membery of the class ofx (or the classpointed to byxp). However, ifx orxprefers to a dependent type that is not the current instantiation,the type ofy is always dependent. Ifx orxp refers to a non-dependent type or refers to thecurrent instantiation, the type ofy is the type of theclass member access expression.]
In 13.8 [temp.res] paragraph 3, replace
Aqualified-name that refers to a type and that dependson atemplate-parameter (13.8.3 [temp.dep]) shallbe prefixed by the keywordtypename.
with
Aqualified-id that refers to a type and that depends onatemplate-parameter (13.8.3 [temp.dep]) butdoes not refer to a member of the current instantiation shall beprefixed by the keywordtypename.
Note: the wording for this paragraph was changed in TC1. Thewords shown here are the pre-TC1 words.
In 13.3 [temp.names] paragraph 4, replace
When the name of a member template specialization appears after. or-> in apostfix-expression, orafter anested-name-specifier in aqualified-id,and thepostfix-expression orqualified-id explicitlydepends on atemplate-parameter (13.8.3 [temp.dep]),the member template name must be prefixed by the keywordtemplate. Otherwise the name is assumed to name anon-template.
with
When the name of a member template specialization appears after. or-> in apostfix-expression, orafter anested-name-specifier in aqualified-id,and thepostfix-expression orqualified-id explicitlydepends on atemplate-parameter (13.8.3 [temp.dep])but does not refer to a member of the current instantiation(13.8.3.2 [temp.dep.type]), the member template name mustbe prefixed by the keywordtemplate. Otherwise the nameis assumed to name a non-template.
In 13.8.2 [temp.local] paragraph 2, remove thefollowing text, which was added forissue 108.The updated definition of dependent name now addresses this case.
Within the scope of a class template, when the unqualified name ofa nested class of the class template is referred to, it isequivalent to the name of the nested class qualified by the nameof the enclosing class template. [Example:
template <class T> struct A {class B {};// B is equivalent to A::B, which is equivalent to A<T>::B,// which is dependent.class C : B { };};—end example]