Files
2025-10-25 03:02:53 +03:00

344 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.3Dependent 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.3Type-dependent expressions"), [[temp.dep.constexpr]](temp.dep.constexpr "13.8.3.4Value-dependent expressions"))[.](#1.sentence-4)
A [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") is never dependent in a specialization and
is therefore replaced during lookup for that specialization ([[basic.lookup]](basic.lookup "6.5Name 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.3Conversion 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.1Point 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.1General[temp.res.general]")
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names 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.1General[temp.res.general]") are
its [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") (if any) and
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") and[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") (if any)[.](#3.sentence-1)
A [*typename-specifier*](#nt:typename-specifier "13.8.1General[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.3Simple type specifiers[dcl.type.simple]") ([[dcl.type.simple]](dcl.type.simple "9.2.9.3Simple 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.5Qualified 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.1General[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.1General[temp.res.general]"),[*type-requirement*](expr.prim.req.type#nt:type-requirement "7.5.8.3Type requirements[expr.prim.req.type]"),[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"),[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]"),[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1General[class.derived.general]"),[*using-enum-declarator*](enum.udecl#nt:using-enum-declarator "9.8.2The using enum declaration[enum.udecl]"),
or
- [(4.2)](#4.2)
a [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") of a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1General[class.mem.general]"), or
- [(4.3)](#4.3)
a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") of a
* [(4.3.1)](#4.3.1)
[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8New[expr.new]"),
* [(4.3.2)](#4.3.2)
[*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]"),
* [(4.3.3)](#4.3.3)
[*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]"),
* [(4.3.4)](#4.3.4)
[*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]"),
* [(4.3.5)](#4.3.5)
default argument of a [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]"), or
* [(4.3.6)](#4.3.6)
[*type-id*](dcl.name#nt:type-id "9.3.2Type 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.1General[dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a
* [(4.4.1)](#4.4.1)
[*simple-declaration*](dcl.pre#nt:simple-declaration "9.1Preamble[dcl.pre]") or [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]") in namespace scope,
* [(4.4.2)](#4.4.2)
[*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]"),
* [(4.4.3)](#4.4.3)
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]"),[116](#footnote-116 "This includes friend function declarations.") unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") appears in a default argument,
* [(4.4.4)](#4.4.4)
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") in a [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") of a function or function template declaration
whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is qualified,
unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") appears in a default argument,
* [(4.4.5)](#4.4.5)
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") in a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") or [*requirement-parameter-list*](expr.prim.req.general#nt:requirement-parameter-list "7.5.8.1General[expr.prim.req.general]"),
unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") appears in a default argument, or
* [(4.4.6)](#4.4.6)
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") of a [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") (which necessarily declares a constant template parameter)[.](#4.sentence-1)
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") ([[basic.splice]](basic.splice "6.6Splice 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.2Type names[dcl.name]")using Alias = [:^^int:]; // OK, in a [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type 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.2Type 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.1General[dcl.decl.general]")auto h() -> [:^^S:]<T*>; // OK, [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")using enum [:^^Enum:]; // OK, [*using-enum-declarator*](enum.udecl#nt:using-enum-declarator "9.8.2The 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.3Qualified 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.10The using declaration[namespace.udecl]") whose terminal name is dependent
is interpreted as a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") if the [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The 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.1Preamble[dcl.pre]")s that fail ([[dcl.pre]](dcl.pre "9.1Preamble")),
can be generated for a templated entity
or a substatement of a constexpr if statement ([[stmt.if]](stmt.if "8.5.2The 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.1Preamble[dcl.pre]")s that fail,
can be generated for the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound 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.1Preamble[dcl.pre]")s that fail,
can be generated for a default [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") and
the default [*template-argument*](temp.names#nt:template-argument "13.3Names 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.8Alias 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.3Constrained 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.1Preamble[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.10The 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.10The 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.7Constant 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.3Names 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.5Exception specifications[except.spec]")*s* of function templates and default
arguments and [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")*s* of
member functions of class templates are considered definitions ([[temp.decls]](temp.decls "13.7Template declarations"))[.](#7.sentence-1)
— *end note*]
[116)](#footnote-116)[116)](#footnoteref-116)
This includes friend function declarations[.](#footnote-116.sentence-1)