13 Templates [temp]

13.8 Name resolution [temp.res]

13.8.1 General [temp.res.general]

Three kinds of names can be used within a template definition:
A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.
[Example 1: // no B declared here class X; template<class T> class Y { class Z; // forward declaration of member class void f() { X* a1; // declare pointer to X T* a2; // declare pointer to T Y* a3; // declare pointer to Y<T> Z* a4; // declare pointer to Z typedef typename T::A TA; TA* a5; // declare pointer to T's A typename T::A* a6; // declare pointer to T's A T::A* a7; // error: no visible declaration of a7 // T​::​A is not a type name; multiplication of T​::​A by a7 B* a8; // error: no visible declarations of B and a8 // B is not a type name; multiplication of B by a8 } }; — end example]
A typename-specifier denotes the type or class template denoted by the simple-type-specifier ([dcl.type.simple]) formed by omitting the keyword typename.
The usual qualified name lookup ([basic.lookup.qual]) is used to find the qualified-id even in the presence of typename.
[Example 2: struct A { struct X { }; int X; }; struct B { struct X { }; }; template<class T> void f(T t) { typename T::X x; } void foo() { A a; B b; f(b); // OK: T​::​X refers to B​::​X f(a); // error: T​::​X refers to the data member A​::​X not the struct A​::​X } — end example]
A qualified name used as the name in a class-or-decltype ([class.derived]) or an elaborated-type-specifier is implicitly assumed to name a type, without the use of the typename keyword.
In a nested-name-specifier that immediately contains a nested-name-specifier that depends on a template parameter, the identifier or simple-template-id is implicitly assumed to name a type, without the use of the typename keyword.
[Note 1:
The typename keyword is not permitted by the syntax of these constructs.
— end note]
A qualified-id is assumed to name a type if
A qualified name is said to be in a type-id-only context if it appears in a type-id, new-type-id, or defining-type-id and the smallest enclosing type-id, new-type-id, or defining-type-id is a new-type-id, defining-type-id, trailing-return-type, default argument of a type-parameter of a template, or type-id of a static_­cast, const_­cast, reinterpret_­cast, or dynamic_­cast.
[Example 3: template<class T> T::R f(); // OK, return type of a function declaration at global scope template<class T> void f(T::R); // ill-formed, no diagnostic required: attempt to declare // a void variable template template<class T> struct S { using Ptr = PtrTraits<T>::Ptr; // OK, in a defining-type-id T::R f(T::P p) { // OK, class scope return static_cast<T::R>(p); // OK, type-id of a static_­cast } auto g() -> S<T*>::Ptr; // OK, trailing-return-type }; template<typename T> void f() { void (*pf)(T::X); // variable pf of type void* initialized with T​::​X void g(T::X); // error: T​::​X at block scope does not denote a type // (attempt to declare a void variable) } — end example]
A qualified-id that refers to a member of an unknown specialization, that is not prefixed by typename, and that is not otherwise assumed to name a type (see above) denotes a non-type.
[Example 4: template <class T> void f(int i) { T::x * i; // expression, not the declaration of a variable i } struct Foo { typedef int x; }; struct Bar { static int const x = 5; }; int main() { f<Bar>(1); // OK f<Foo>(1); // error: Foo​::​x is a type } — end example]
Within the definition of a class template or within the definition of a member of a class template following the declarator-id, the keyword typename is not required when referring to a member of the current instantiation ([temp.dep.type]).
[Example 5: template<class T> struct A { typedef int B; B b; // OK, no typename required }; — end example]
The validity of a template may be checked prior to any instantiation.
[Note 2:
Knowing which names are type names allows the syntax of every template to be checked in this way.
— end note]
The program is ill-formed, no diagnostic required, if:
  • no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated, or
  • no substitution of template arguments into a type-constraint or requires-clause would result in a valid expression, or
  • every valid specialization of a variadic template requires an empty template parameter pack, or
  • a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or
  • the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct in any actual instantiation of the template.
    [Note 3:
    This can happen in situations including the following:
    • a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is performed, or
    • lookup for a name in the template definition found a using-declaration, but the lookup in the corresponding scope in the instantiation does not find any declarations because the using-declaration was a pack expansion and the corresponding pack is empty, or
    • an instantiation uses a default argument or default template argument that had not been defined at the point at which the template was defined, or
    • constant expression evaluation within the template instantiation uses
      • the value of a const object of integral or unscoped enumeration type or
      • the value of a constexpr object or
      • the value of a reference or
      • the definition of a constexpr function,
      and that entity was not defined when the template was defined, or
    • a class template specialization or variable template specialization that is specified by a non-dependent simple-template-id is used by the template, and either it is instantiated from a partial specialization that was not defined when the template was defined or it names an explicit specialization that was not declared when the template was defined.
    — end note]
Otherwise, no diagnostic shall be issued for a template for which a valid specialization can be generated.
[Note 4:
If a template is instantiated, errors will be diagnosed according to the other rules in this document.
Exactly when these errors are diagnosed is a quality of implementation issue.
— end note]
[Example 6: int j; template<class T> class X { void f(T t, int i, char* p) { t = i; // diagnosed if X​::​f is instantiated, and the assignment to t is an error p = i; // may be diagnosed even if X​::​f is not instantiated p = j; // may be diagnosed even if X​::​f is not instantiated } void g(T t) { +; // may be diagnosed even if X​::​g is not instantiated } }; template<class... T> struct A { void operator++(int, T... t); // error: too many parameters }; template<class... T> union X : T... { }; // error: union with base class template<class... T> struct A : T..., T... { }; // error: duplicate base class — end example]
When looking for the declaration of a name used in a template definition, the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) are used for non-dependent names.
The lookup of names dependent on the template parameters is postponed until the actual template argument is known ([temp.dep]).
[Example 7: #include <iostream> using namespace std; template<class T> class Set { T* p; int cnt; public: Set(); Set<T>(const Set<T>&); void printall() { for (int i = 0; i<cnt; i++) cout << p[i] << '\n'; } };
In the example, i is the local variable i declared in printall, cnt is the member cnt declared in Set, and cout is the standard output stream declared in iostream.
However, not every declaration can be found this way; the resolution of some names is postponed until the actual template-arguments are known.
For example, even though the name operator<< is known within the definition of printall() and a declaration of it can be found in <iostream>, the actual declaration of operator<< needed to print p[i] cannot be known until it is known what type T is ([temp.dep]).
— end example]
If a name does not depend on a template-parameter (as defined in [temp.dep]), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation.
[Example 8: void f(char); template<class T> void g(T t) { f(1); // f(char) f(T(1)); // dependent f(t); // dependent dd++; // not dependent; error: declaration for dd not found } enum E { e }; void f(E); double dd; void h() { g(e); // will cause one call of f(char) followed by two calls of f(E) g('a'); // will cause three calls of f(char) } — end example]
[Note 5:
For purposes of name lookup, default arguments and noexcept-specifiers of function templates and default arguments and noexcept-specifiers of member functions of class templates are considered definitions ([temp.decls]).
— end note]
This includes friend function declarations.