344 lines
19 KiB
Markdown
344 lines
19 KiB
Markdown
[temp.res.general]
|
||
|
||
# 13 Templates [[temp]](./#temp)
|
||
|
||
## 13.8 Name resolution [[temp.res]](temp.res#general)
|
||
|
||
### 13.8.1 General [temp.res.general]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4754)
|
||
|
||
A name that appears in a declaration D of a template T is looked up
|
||
from where it appears
|
||
in an unspecified declaration of T that either is D itself or is reachable from D and
|
||
from which no other declaration of T that contains the usage of the name is reachable[.](#1.sentence-1)
|
||
|
||
If the name is dependent (as specified in [[temp.dep]](temp.dep "13.8.3 Dependent names")),
|
||
it is looked up for each specialization (after substitution)
|
||
because the lookup depends on a template parameter[.](#1.sentence-2)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
Some dependent names are also looked up during parsing to determine
|
||
that they are dependent or to interpret following < tokens[.](#1.sentence-3)
|
||
|
||
Uses of other names might be type-dependent or
|
||
value-dependent ([[temp.dep.expr]](temp.dep.expr "13.8.3.3 Type-dependent expressions"), [[temp.dep.constexpr]](temp.dep.constexpr "13.8.3.4 Value-dependent expressions"))[.](#1.sentence-4)
|
||
|
||
A [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") is never dependent in a specialization and
|
||
is therefore replaced during lookup for that specialization ([[basic.lookup]](basic.lookup "6.5 Name lookup"))[.](#1.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#example-1)*: struct A { operator int(); };template<class B, class T>struct D : B { T get() { return operator T(); } // [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") is dependent};int f(D<A, int> d) { return d.get(); } // OK, lookup finds A::operator int â *end example*]
|
||
|
||
[*Example [2](#example-2)*: 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*]
|
||
|
||
[*Example [3](#example-3)*: struct A {struct B { /* ... */ }; int a; int Y;};
|
||
|
||
int a;
|
||
|
||
template<class T> struct Y : T {struct B { /* ... */ };
|
||
B b; // The B defined in Yvoid f(int i) { a = i; } // ::a Y* p; // Y<T>};
|
||
|
||
Y<A> ya;
|
||
|
||
The members A::B, A::a, and A::Y of the template argument A do not affect the binding of names in Y<A>[.](#1.sentence-6)
|
||
|
||
â *end example*]
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4828)
|
||
|
||
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]](temp.point "13.8.4.1 Point of instantiation"))
|
||
but is not found by lookup for the specialization,
|
||
the program is ill-formed, no diagnostic required[.](#2.sentence-1)
|
||
|
||
[typename-specifier:](#nt:typename-specifier "13.8.1 General [temp.res.general]")
|
||
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4842)
|
||
|
||
The component names of a [*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]") are
|
||
its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") (if any) and
|
||
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") (if any)[.](#3.sentence-1)
|
||
|
||
A [*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]") denotes the type or class template
|
||
denoted by the [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") ([[dcl.type.simple]](dcl.type.simple "9.2.9.3 Simple type specifiers"))
|
||
formed by omitting the keyword typename[.](#3.sentence-2)
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
The usual qualified name lookup ([[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup")) applies
|
||
even in the presence of typename[.](#3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [4](#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); // 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*]
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4877)
|
||
|
||
A [*type-only context*](#def:context,type-only "13.8.1 General [temp.res.general]") is defined as follows:
|
||
A qualified or unqualified name is said to be in
|
||
a type-only context if it is the terminal name of
|
||
|
||
- [(4.1)](#4.1)
|
||
|
||
a[*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]"),[*type-requirement*](expr.prim.req.type#nt:type-requirement "7.5.8.3 Type requirements [expr.prim.req.type]"),[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"),[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1 General [class.derived.general]"),[*using-enum-declarator*](enum.udecl#nt:using-enum-declarator "9.8.2 The using enum declaration [enum.udecl]"),
|
||
or
|
||
|
||
- [(4.2)](#4.2)
|
||
|
||
a [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") of a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1 General [class.mem.general]"), or
|
||
|
||
- [(4.3)](#4.3)
|
||
|
||
a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") of a
|
||
* [(4.3.1)](#4.3.1)
|
||
|
||
[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]"),
|
||
|
||
* [(4.3.2)](#4.3.2)
|
||
|
||
[*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]"),
|
||
|
||
* [(4.3.3)](#4.3.3)
|
||
|
||
[*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]"),
|
||
|
||
* [(4.3.4)](#4.3.4)
|
||
|
||
[*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]"),
|
||
|
||
* [(4.3.5)](#4.3.5)
|
||
|
||
default argument of a [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]"), or
|
||
|
||
* [(4.3.6)](#4.3.6)
|
||
|
||
[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of astatic_cast,const_cast,reinterpret_cast, ordynamic_cast, or
|
||
|
||
- [(4.4)](#4.4)
|
||
|
||
a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of a
|
||
* [(4.4.1)](#4.4.1)
|
||
|
||
[*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [dcl.pre]") or [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]") in namespace scope,
|
||
|
||
* [(4.4.2)](#4.4.2)
|
||
|
||
[*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]"),
|
||
|
||
* [(4.4.3)](#4.4.3)
|
||
|
||
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]"),[116](#footnote-116 "This includes friend function declarations.") unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appears in a default argument,
|
||
|
||
* [(4.4.4)](#4.4.4)
|
||
|
||
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") in a [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") of a function or function template declaration
|
||
whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is qualified,
|
||
unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appears in a default argument,
|
||
|
||
* [(4.4.5)](#4.4.5)
|
||
|
||
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") in a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") or [*requirement-parameter-list*](expr.prim.req.general#nt:requirement-parameter-list "7.5.8.1 General [expr.prim.req.general]"),
|
||
unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appears in a default argument, or
|
||
|
||
* [(4.4.6)](#4.4.6)
|
||
|
||
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") of a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") (which necessarily declares a constant template parameter)[.](#4.sentence-1)
|
||
|
||
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") ([[basic.splice]](basic.splice "6.6 Splice specifiers"))
|
||
is said to be in a type-only context
|
||
if a hypothetical qualified name appearing in the same position
|
||
would be in a type-only context[.](#4.sentence-2)
|
||
|
||
[*Example [5](#example-5)*: template<class T> T::R f(); // OK, return type of a function declaration at global scopetemplate<class T> void f(T::R); // ill-formed, no diagnostic required: attempt to declare// a void variable templateenum class Enum { A, B, C };template<class T> struct S {using Ptr = PtrTraits<T>::Ptr; // OK, in a [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]")using Alias = [:^^int:]; // OK, in a [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]") T::R f(T::P p) { // OK, class scopereturn static_cast<T::R>(p); // OK, [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a static_cast}auto g() -> S<T*>::Ptr; // OK, [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")auto h() -> [:^^S:]<T*>; // OK, [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")using enum [:^^Enum:]; // OK, [*using-enum-declarator*](enum.udecl#nt:using-enum-declarator "9.8.2 The using enum declaration [enum.udecl]")};template<typename T> void f() {void (*pf)(T::X); // variable pf of type void* initialized with T::Xvoid g(T::X); // error: T::X at block scope does not denote a type// (attempt to declare a void variable)} â *end example*]
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4957)
|
||
|
||
A [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") whose terminal name is dependent and that is in a type-only context
|
||
is considered to denote a type[.](#5.sentence-1)
|
||
|
||
A name
|
||
that refers to a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") whose terminal name is dependent
|
||
is interpreted as a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") if the [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") uses the keyword typename[.](#5.sentence-2)
|
||
|
||
[*Example [6](#example-6)*: 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*]
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4986)
|
||
|
||
The validity of a templated entity may be checked prior to any instantiation[.](#6.sentence-1)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
Knowing which names are type names allows the syntax of every template
|
||
to be checked in this way[.](#6.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
The program is ill-formed, no diagnostic required, if
|
||
|
||
- [(6.1)](#6.1)
|
||
|
||
no valid specialization,
|
||
ignoring [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]")s that fail ([[dcl.pre]](dcl.pre "9.1 Preamble")),
|
||
can be generated for a templated entity
|
||
or a substatement of a constexpr if statement ([[stmt.if]](stmt.if "8.5.2 The if statement"))
|
||
within a templated entity
|
||
and the innermost enclosing template is not instantiated, or
|
||
|
||
- [(6.2)](#6.2)
|
||
|
||
no valid specialization,
|
||
ignoring [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]")s that fail,
|
||
can be generated for the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of an expansion statement and there is no instantiation of it, or
|
||
|
||
- [(6.3)](#6.3)
|
||
|
||
no valid specialization,
|
||
ignoring [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]")s that fail,
|
||
can be generated for a default [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") and
|
||
the default [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") is not used in any instantiation, or
|
||
|
||
- [(6.4)](#6.4)
|
||
|
||
no specialization of an alias template ([[temp.alias]](temp.alias "13.7.8 Alias templates")) is valid and
|
||
no specialization of the alias template is named in the program, or
|
||
|
||
- [(6.5)](#6.5)
|
||
|
||
any [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") 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
|
||
|
||
- [(6.6)](#6.6)
|
||
|
||
every valid specialization of a variadic template requires an empty template
|
||
parameter pack, or
|
||
|
||
- [(6.7)](#6.7)
|
||
|
||
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*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]") that fails)
|
||
that does not depend on a template parameter, or
|
||
|
||
- [(6.8)](#6.8)
|
||
|
||
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[.](#6.sentence-3)
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
This can happen in situations including the following:
|
||
|
||
- [(6.9)](#6.9)
|
||
|
||
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
|
||
|
||
- [(6.10)](#6.10)
|
||
|
||
lookup for a name in the template definition found a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]"),
|
||
but the lookup in the corresponding scope in the instantiation
|
||
does not find any declarations because the [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") was a pack expansion and the corresponding pack is empty, or
|
||
|
||
- [(6.11)](#6.11)
|
||
|
||
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
|
||
|
||
- [(6.12)](#6.12)
|
||
|
||
[constant expression evaluation](expr.const "7.7 Constant expressions [expr.const]") within the template
|
||
instantiation uses
|
||
* [(6.12.1)](#6.12.1)
|
||
|
||
the value of a const object of integral or unscoped enumeration type or
|
||
|
||
* [(6.12.2)](#6.12.2)
|
||
|
||
the value of a constexpr object or
|
||
|
||
* [(6.12.3)](#6.12.3)
|
||
|
||
the value of a reference or
|
||
|
||
* [(6.12.4)](#6.12.4)
|
||
|
||
the definition of a constexpr function,
|
||
|
||
and that entity was not defined when the template was defined, or
|
||
|
||
- [(6.13)](#6.13)
|
||
|
||
a class template specialization or variable template specialization that
|
||
is specified by a non-dependent [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") 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[.](#6.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
If a template is instantiated, errors will be diagnosed according
|
||
to the other rules in this document[.](#6.sentence-5)
|
||
|
||
Exactly when these errors are diagnosed is a quality of implementation issue[.](#6.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [7](#example-7)*: 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 X<T>::g(t); // OK X<T>::h(); // 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 classtemplate<class... T> struct A : T..., T... { }; // error: duplicate base class â *end example*]
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5100)
|
||
|
||
[*Note [6](#note-6)*:
|
||
|
||
For purposes of name lookup, default arguments and[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")*s* of function templates and default
|
||
arguments and [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")*s* of
|
||
member functions of class templates are considered definitions ([[temp.decls]](temp.decls "13.7 Template declarations"))[.](#7.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[116)](#footnote-116)[116)](#footnoteref-116)
|
||
|
||
This includes friend function declarations[.](#footnote-116.sentence-1)
|