[temp.res.general] (original) (raw)
13 Templates [temp]
13.8 Name resolution [temp.res]
13.8.1 General [temp.res.general]
A name that appears in a declaration D of a template T is looked up from where it appears in an unspecified declaration of Tthat either is D itself or is reachable from D and from which no other declaration of Tthat contains the usage of the name is reachable.
If the name is dependent (as specified in [temp.dep]), it is looked up for each specialization (after substitution) because the lookup depends on a template parameter.
[Note 1:
Some dependent names are also looked up during parsing to determine that they are dependent or to interpret following < tokens.
A using-declarator is never dependent in a specialization and is therefore replaced during lookup for that specialization ([basic.lookup]).
— _end note_]
[Example 1: struct A { operator int(); };template<class B, class T> struct D : B { T get() { return operator T(); } };int f(D<A, int> d) { return d.get(); } — _end example_]
[Example 2: void f(char);template<class T> void g(T t) { f(1); f(T(1)); f(t); dd++; } enum E { e };void f(E);double dd;void h() { g(e); g('a'); } — _end example_]
[Example 3: struct A { struct B { };int a;int Y;};int a;template<class T> struct Y : T { struct B { }; B b; void f(int i) { a = i; } Y* p; }; Y<A> ya;
The members A::B, A::a, and A::Yof the template argument Ado not affect the binding of names in Y<A>.
— _end example_]
If the validity or meaning of the program would be changed by considering a default argument or default template argument introduced in a declaration that is reachable from the point of instantiation of a specialization ([temp.point]) but is not found by lookup for the specialization, the program is ill-formed, no diagnostic required.
[Note 2:
The usual qualified name lookup ([basic.lookup.qual]) applies even in the presence of typename.
— _end note_]
[Example 4: 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); f(a); } — _end example_]
A qualified or unqualified name is said to be in a type-only contextif it is the terminal name of
- atypename-specifier,type-requirement,nested-name-specifier,elaborated-type-specifier,class-or-decltype, or
- a simple-type-specifier of a friend-type-specifier, or
- a type-specifier of a
- new-type-id,
- defining-type-id,
- conversion-type-id,
- trailing-return-type,
- default argument of a type-parameter, or
- type-id of astatic_cast,const_cast,reinterpret_cast, ordynamic_cast, or
- a decl-specifier of the decl-specifier-seq of a
- simple-declaration or function-definition in namespace scope,
- member-declaration,
- parameter-declaration in a member-declaration,116unless that parameter-declaration appears in a default argument,
- parameter-declaration in a declaratorof a function or function template declaration whose declarator-id is qualified, unless that parameter-declarationappears in a default argument,
- parameter-declaration in a lambda-declaratoror requirement-parameter-list, unless that parameter-declaration appears in a default argument, or
- parameter-declaration of a template-parameter(which necessarily declares a constant template parameter).
[Example 5: template<class T> T::R f(); template<class T> void f(T::R); template<class T> struct S { using Ptr = PtrTraits<T>::Ptr; T::R f(T::P p) { return static_cast<T::R>(p); } auto g() -> S<T*>::Ptr; };template<typename T> void f() { void (*pf)(T::X); void g(T::X); } — _end example_]
A qualified-idwhose terminal name is dependent and that is in a type-only context is considered to denote a type.
[Example 6: template <class T> void f(int i) { T::x * i; } struct Foo { typedef int x;};struct Bar { static int const x = 5;};int main() { f<Bar>(1); f<Foo>(1); } — _end example_]
The validity of a templated entity may be checked prior to any instantiation.
[Note 3:
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, ignoring static_assert-declarations that fail ([dcl.pre]), can be generated for a templated entity or a substatement of a constexpr if statement ([stmt.if]) within a templated entity and the innermost enclosing template is not instantiated, or
- no valid specialization, ignoring static_assert-declarations that fail, can be generated for a default template-argument and the default template-argument is not used in any instantiation, or
- no specialization of an alias template ([temp.alias]) is valid and no specialization of the alias template is named in the program, or
- any constraint-expression in the program, introduced or otherwise, has (in its normal form) an atomic constraint A where no satisfaction check of A could be well-formed and no satisfaction check of A is performed, or
- every valid specialization of a variadic template requires an empty template parameter pack, or
- a hypothetical instantiation of a templated entity immediately following its definition would be ill-formed due to a construct (other than a static_assert-declaration that fails) 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 templated entity.
[Note 4:
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-declarationwas 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_]
[Note 5:
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 7: int j;template<class T> class X { void f(T t, int i, char* p) { t = i; p = i; p = j; X<T>::g(t); X<T>::h(); } void g(T t) { +; } };template<class... T> struct A { void operator++(int, T... t); };template<class... T> union X : T... { }; template<class... T> struct A : T..., T... { }; — _end example_]