[temp.dep.type] (original) (raw)

13 Templates [temp]

13.8 Name resolution [temp.res]

13.8.3 Dependent names [temp.dep]

13.8.3.2 Dependent types [temp.dep.type]

A name or template-id refers to thecurrent instantiationif it is

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

[Note 1:

Using a parenthesized variable name breaks the equivalence.

— _end note_]

[Example 1: template <class T> class A { A* p1; A<T>* p2; A<T*> p3; ::A<T>* p4; class B { B* p1; A<T>::B* p2; typename A<T*>::B* p3; };};template <class T> class A<T*> { A<T*>* p1; A<T>* p2; };template <class T1, class T2, int I> struct B { B<T1, T2, I>* b1; B<T2, T1, I>* b2; 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; B<my_T1, T2, my_I2>* b4; B<my_T1, T2, my_I3>* b5; B<my_T1, T2, my_I4>* b6; B<my_T1, T2, my_I5>* b7; }; — _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; }; — _end example_]

— _end note_]

A qualified ([basic.lookup.qual]) or unqualified name is amember of the current instantiationif

[Example 3: template <class T> class A { static const int i = 5;int n1[i]; int n2[A::i]; int n3[A<T>::i]; int f();};template <class T> int A<T>::f() { return i; } — _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; } template void g(C); — _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; } int g() { return m; } };template int C<B>::f(); template int C<B>::g(); — _end example_]

An initializer is dependent if any constituent expression ([intro.execution]) of the initializer is type-dependent.

A placeholder type ([dcl.spec.auto.general]) is dependent if it designates a type deduced from a dependent initializer.

[Example 6: template<class T, class V> struct S { S(T); };template<class U> struct A { template<class T> using X = S<T, U>;template<class T> using Y = S<T, int>;void f() { new X(1); new Y(1); } }; — _end example_]

A type is dependent if it is

[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_]