1482 lines
83 KiB
Markdown
1482 lines
83 KiB
Markdown
[temp.res]
|
||
|
||
# 13 Templates [[temp]](./#temp)
|
||
|
||
## 13.8 Name resolution [temp.res]
|
||
|
||
### [13.8.1](#general) General [[temp.res.general]](temp.res.general)
|
||
|
||
[1](#general-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[.](#general-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[.](#general-1.sentence-2)
|
||
|
||
[*Note [1](#general-note-1)*:
|
||
|
||
Some dependent names are also looked up during parsing to determine
|
||
that they are dependent or to interpret following < tokens[.](#general-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"))[.](#general-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"))[.](#general-1.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#general-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](#general-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](#general-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>[.](#general-1.sentence-6)
|
||
|
||
â *end example*]
|
||
|
||
[2](#general-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[.](#general-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](#general-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)[.](#general-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[.](#general-3.sentence-2)
|
||
|
||
[*Note [2](#general-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[.](#general-3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [4](#general-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](#general-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)](#general-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)](#general-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)](#general-4.3)
|
||
|
||
a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") of a
|
||
* [(4.3.1)](#general-4.3.1)
|
||
|
||
[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]"),
|
||
|
||
* [(4.3.2)](#general-4.3.2)
|
||
|
||
[*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]"),
|
||
|
||
* [(4.3.3)](#general-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)](#general-4.3.4)
|
||
|
||
[*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]"),
|
||
|
||
* [(4.3.5)](#general-4.3.5)
|
||
|
||
default argument of a [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]"), or
|
||
|
||
* [(4.3.6)](#general-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)](#general-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)](#general-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)](#general-4.4.2)
|
||
|
||
[*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]"),
|
||
|
||
* [(4.4.3)](#general-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)](#general-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)](#general-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)](#general-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)[.](#general-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[.](#general-4.sentence-2)
|
||
|
||
[*Example [5](#general-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](#general-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[.](#general-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[.](#general-5.sentence-2)
|
||
|
||
[*Example [6](#general-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](#general-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[.](#general-6.sentence-1)
|
||
|
||
[*Note [3](#general-note-3)*:
|
||
|
||
Knowing which names are type names allows the syntax of every template
|
||
to be checked in this way[.](#general-6.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
The program is ill-formed, no diagnostic required, if
|
||
|
||
- [(6.1)](#general-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)](#general-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)](#general-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)](#general-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)](#general-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)](#general-6.6)
|
||
|
||
every valid specialization of a variadic template requires an empty template
|
||
parameter pack, or
|
||
|
||
- [(6.7)](#general-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)](#general-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[.](#general-6.sentence-3)
|
||
|
||
[*Note [4](#general-note-4)*:
|
||
|
||
This can happen in situations including the following:
|
||
|
||
- [(6.9)](#general-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)](#general-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)](#general-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)](#general-6.12)
|
||
|
||
[constant expression evaluation](expr.const "7.7 Constant expressions [expr.const]") within the template
|
||
instantiation uses
|
||
* [(6.12.1)](#general-6.12.1)
|
||
|
||
the value of a const object of integral or unscoped enumeration type or
|
||
|
||
* [(6.12.2)](#general-6.12.2)
|
||
|
||
the value of a constexpr object or
|
||
|
||
* [(6.12.3)](#general-6.12.3)
|
||
|
||
the value of a reference or
|
||
|
||
* [(6.12.4)](#general-6.12.4)
|
||
|
||
the definition of a constexpr function,
|
||
|
||
and that entity was not defined when the template was defined, or
|
||
|
||
- [(6.13)](#general-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[.](#general-6.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [5](#general-note-5)*:
|
||
|
||
If a template is instantiated, errors will be diagnosed according
|
||
to the other rules in this document[.](#general-6.sentence-5)
|
||
|
||
Exactly when these errors are diagnosed is a quality of implementation issue[.](#general-6.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [7](#general-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](#general-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5100)
|
||
|
||
[*Note [6](#general-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"))[.](#general-7.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[116)](#footnote-116)[116)](#footnoteref-116)
|
||
|
||
This includes friend function declarations[.](#footnote-116.sentence-1)
|
||
|
||
### [13.8.2](#temp.local) Locally declared names [[temp.local]](temp.local)
|
||
|
||
[1](#temp.local-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5110)
|
||
|
||
Like normal (non-template) classes, class templates have an
|
||
injected-class-name ([[class.pre]](class.pre "11.1 Preamble"))[.](#temp.local-1.sentence-1)
|
||
|
||
The
|
||
injected-class-name can be used
|
||
as a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") or a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]")[.](#temp.local-1.sentence-2)
|
||
|
||
When it is used with a[*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]"),
|
||
as a [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") for a type template template parameter,
|
||
or as the final identifier in the [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") of
|
||
a friend class template declaration,
|
||
it is a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") that refers to the
|
||
class template itself[.](#temp.local-1.sentence-3)
|
||
|
||
Otherwise, it is a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") equivalent to the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") followed by
|
||
the template argument list ([[temp.decls.general]](temp.decls.general "13.7.1 General"), [[temp.arg.general]](temp.arg.general "13.4.1 General"))
|
||
of the class template
|
||
enclosed in <>[.](#temp.local-1.sentence-4)
|
||
|
||
[2](#temp.local-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5130)
|
||
|
||
When the injected-class-name of a class template specialization or
|
||
partial specialization is used as a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]"),
|
||
it is equivalent to the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") followed by the[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* of the class template specialization or partial
|
||
specialization enclosed in<>[.](#temp.local-2.sentence-1)
|
||
|
||
[*Example [1](#temp.local-example-1)*: template<template<class> class T> class A { };template<class T> class Y;template<> class Y<int> { Y* p; // meaning Y<int> Y<char>* q; // meaning Y<char> A<Y>* a; // meaning A<::Y>class B {template<class> friend class Y; // meaning ::Y};}; â *end example*]
|
||
|
||
[3](#temp.local-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5153)
|
||
|
||
The injected-class-name of a class template or class
|
||
template specialization can be used as either
|
||
a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") or a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") wherever it is named[.](#temp.local-3.sentence-1)
|
||
|
||
[*Example [2](#temp.local-example-2)*: template <class T> struct Base { Base* p;};
|
||
|
||
template <class T> struct Derived: public Base<T> {typename Derived::Base* p; // meaning Derived::Base<T>};
|
||
|
||
template<class T, template<class> class U = T::Base> struct Third { };
|
||
Third<Derived<int> > t; // OK, default argument uses injected-class-name as a template â *end example*]
|
||
|
||
[4](#temp.local-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5173)
|
||
|
||
A lookup that finds an injected-class-name ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup")) can result in an ambiguity in
|
||
certain cases (for example, if it is found in more than one
|
||
base class)[.](#temp.local-4.sentence-1)
|
||
|
||
If all of the injected-class-names that are
|
||
found refer to specializations of the same class template,
|
||
and if the name
|
||
is used as a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]"),
|
||
the reference refers to the class template itself and not a
|
||
specialization thereof, and is not ambiguous[.](#temp.local-4.sentence-2)
|
||
|
||
[*Example [3](#temp.local-example-3)*: template <class T> struct Base { };template <class T> struct Derived: Base<int>, Base<char> {typename Derived::Base b; // error: ambiguoustypename Derived::Base<double> d; // OK}; â *end example*]
|
||
|
||
[5](#temp.local-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5193)
|
||
|
||
When the normal name of the template (i.e., the name from
|
||
the enclosing scope, not the injected-class-name) is
|
||
used,
|
||
it always refers to the class template itself and not a
|
||
specialization of the template[.](#temp.local-5.sentence-1)
|
||
|
||
[*Example [4](#temp.local-example-4)*: template<class T> class X { X* p; // meaning X<T> X<T>* p2;
|
||
X<int>* p3; ::X* p4; // error: missing template argument list// ::X does not refer to the injected-class-name}; â *end example*]
|
||
|
||
[6](#temp.local-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5211)
|
||
|
||
The name of a template parameter
|
||
shall not be bound to any following declaration
|
||
whose locus is contained by the scope
|
||
to which the template parameter belongs[.](#temp.local-6.sentence-1)
|
||
|
||
[*Example [5](#temp.local-example-5)*: template<class T, int i> class Y {int T; // error: template parameter hiddenvoid f() {char T; // error: template parameter hidden}friend void T(); // OK, no name bound};
|
||
|
||
template<class X> class X; // error: hidden by template parameter â *end example*]
|
||
|
||
[7](#temp.local-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5230)
|
||
|
||
Unqualified name lookup considers
|
||
the template parameter scope of a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") immediately after the outermost scope associated with the template declared
|
||
(even if its parent scope does not contain
|
||
the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]"))[.](#temp.local-7.sentence-1)
|
||
|
||
[*Note [1](#temp.local-note-1)*:
|
||
|
||
The scope of a class template,
|
||
including its non-dependent base classes ([[temp.dep.type]](#temp.dep.type "13.8.3.2 Dependent types"), [[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup")),
|
||
is searched before its template parameter scope[.](#temp.local-7.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [6](#temp.local-example-6)*: struct B { };namespace N {typedef void V; template<class T> struct A : B {typedef void C; void f(); template<class U> void g(U); };}template<class V> void N::A<V>::f() { // N::V not considered here V v; // V is still the template parameter, not N::V}template<class B> template<class C> void N::A<B>::g(C) { B b; // B is the base class, not the template parameter C c; // C is the template parameter, not A's C} â *end example*]
|
||
|
||
### [13.8.3](#temp.dep) Dependent names [[temp.dep]](temp.dep)
|
||
|
||
#### [13.8.3.1](#temp.dep.general) General [[temp.dep.general]](temp.dep.general)
|
||
|
||
[1](#temp.dep.general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5268)
|
||
|
||
Inside a template, some constructs have semantics which may differ from one
|
||
instantiation to another[.](#temp.dep.general-1.sentence-1)
|
||
|
||
Such a construct[*depends*](#def:name,dependent "13.8.3.1 General [temp.dep.general]") on the template parameters[.](#temp.dep.general-1.sentence-2)
|
||
|
||
In particular, types and expressions may depend on the type
|
||
and/or
|
||
value of
|
||
template parameters (as determined by the template arguments) and this determines
|
||
the context for name lookup for certain names[.](#temp.dep.general-1.sentence-3)
|
||
|
||
An expression may be[*type-dependent*](#def:expression,type-dependent "13.8.3.1 General [temp.dep.general]") (that is, its type may depend on a template parameter) or[*value-dependent*](#def:expression,value-dependent "13.8.3.1 General [temp.dep.general]") (that is, its value when evaluated as a constant expression ([[expr.const]](expr.const "7.7 Constant expressions"))
|
||
may depend on a template parameter)
|
||
as described below[.](#temp.dep.general-1.sentence-4)
|
||
|
||
[2](#temp.dep.general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5288)
|
||
|
||
A [*dependent call*](#def:call,dependent "13.8.3.1 General [temp.dep.general]") is an expression,
|
||
possibly formed as a non-member candidate for an operator ([[over.match.oper]](over.match.oper "12.2.2.3 Operators in expressions")),
|
||
of the form:
|
||
|
||
[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||
|
||
where the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") is an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") and
|
||
|
||
- [(2.1)](#temp.dep.general-2.1)
|
||
|
||
any of the expressions in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") is a pack
|
||
expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")), or
|
||
|
||
- [(2.2)](#temp.dep.general-2.2)
|
||
|
||
any of the expressions
|
||
or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")*s* in the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") is [type-dependent](#temp.dep.expr "13.8.3.3 Type-dependent expressions [temp.dep.expr]"), or
|
||
|
||
- [(2.3)](#temp.dep.general-2.3)
|
||
|
||
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") is a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") in which any of the template arguments depends
|
||
on a template parameter[.](#temp.dep.general-2.sentence-1)
|
||
|
||
The component name of an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names"))
|
||
is dependent if
|
||
|
||
- [(2.4)](#temp.dep.general-2.4)
|
||
|
||
it is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") whose [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]") is dependent, or
|
||
|
||
- [(2.5)](#temp.dep.general-2.5)
|
||
|
||
it is operator= and
|
||
the current class is a templated entity, or
|
||
|
||
- [(2.6)](#temp.dep.general-2.6)
|
||
|
||
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") is
|
||
the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") in a dependent call[.](#temp.dep.general-2.sentence-2)
|
||
|
||
[*Note [1](#temp.dep.general-note-1)*:
|
||
|
||
Such names
|
||
are looked up only at the point of the template instantiation ([[temp.point]](#temp.point "13.8.4.1 Point of instantiation"))
|
||
in both the context of the template definition and the
|
||
context of the point of instantiation ([[temp.dep.candidate]](#temp.dep.candidate "13.8.4.2 Candidate functions"))[.](#temp.dep.general-2.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[3](#temp.dep.general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5332)
|
||
|
||
[*Example [1](#temp.dep.general-example-1)*: template<class T> struct X : B<T> {typename T::A* pa; void f(B<T>* pb) {static int i = B<T>::i;
|
||
pb->j++; }};
|
||
|
||
The base class nameB<T>,
|
||
the type nameT::A,
|
||
the namesB<T>::i andpb->j explicitly depend on the[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")[.](#temp.dep.general-3.sentence-1)
|
||
|
||
â *end example*]
|
||
|
||
#### [13.8.3.2](#temp.dep.type) Dependent types [[temp.dep.type]](temp.dep.type)
|
||
|
||
[1](#temp.dep.type-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5358)
|
||
|
||
A name or [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") refers to the[*current instantiation*](#def:current_instantiation "13.8.3.2 Dependent types [temp.dep.type]") if it is
|
||
|
||
- [(1.1)](#temp.dep.type-1.1)
|
||
|
||
in the definition of a class template, a nested class of a class template,
|
||
a member of a class template, or a member of a nested class of a class template,
|
||
the [injected-class-name](class.pre#def:injected-class-name "11.1 Preamble [class.pre]") of the class template or nested class,
|
||
|
||
- [(1.2)](#temp.dep.type-1.2)
|
||
|
||
in the definition of a primary class template
|
||
or a member of a primary class template, the name of the
|
||
class template followed by the template argument list of
|
||
its [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") ([[temp.arg]](temp.arg "13.4 Template arguments")) enclosed in<> (or an equivalent template alias specialization),
|
||
|
||
- [(1.3)](#temp.dep.type-1.3)
|
||
|
||
in the definition of a nested class of a class template,
|
||
the name of the nested class referenced as a member of the
|
||
current instantiation,
|
||
|
||
- [(1.4)](#temp.dep.type-1.4)
|
||
|
||
in the definition of a class template partial specialization
|
||
or a member of a class template partial specialization, the name of
|
||
the class template followed by a template argument list
|
||
equivalent to that of the partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial specialization"))
|
||
enclosed in <> (or an equivalent template alias specialization), or
|
||
|
||
- [(1.5)](#temp.dep.type-1.5)
|
||
|
||
in the definition of a templated function,
|
||
the name of a local class ([[class.local]](class.local "11.6 Local class declarations"))[.](#temp.dep.type-1.sentence-1)
|
||
|
||
[2](#temp.dep.type-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5388)
|
||
|
||
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[.](#temp.dep.type-2.sentence-1)
|
||
|
||
A template argument is equivalent to a type template parameter
|
||
if it denotes the same type[.](#temp.dep.type-2.sentence-2)
|
||
|
||
A template argument is equivalent to a constant template parameter
|
||
if it is an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") that names a variable
|
||
that is equivalent to the template parameter[.](#temp.dep.type-2.sentence-3)
|
||
|
||
A variable is equivalent to a template parameter if
|
||
|
||
- [(2.1)](#temp.dep.type-2.1)
|
||
|
||
it has the same type as the template parameter
|
||
(ignoring cv-qualification) and
|
||
|
||
- [(2.2)](#temp.dep.type-2.2)
|
||
|
||
its initializer consists of a single [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") that names the template parameter or, recursively, such a variable[.](#temp.dep.type-2.sentence-4)
|
||
|
||
[*Note [1](#temp.dep.type-note-1)*:
|
||
|
||
Using a parenthesized variable name breaks the equivalence[.](#temp.dep.type-2.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#temp.dep.type-example-1)*: template <class T> class A { A* p1; // A is the current instantiation A<T>* p2; // A<T> is the current instantiation A<T*> p3; // A<T*> is not the current instantiation::A<T>* p4; // ::A<T> is the current instantiationclass B { B* p1; // B is the current instantiation A<T>::B* p2; // A<T>::B is the current instantiationtypename A<T*>::B* p3; // A<T*>::B is not the current instantiation};};
|
||
|
||
template <class T> class A<T*> { A<T*>* p1; // A<T*> is the current instantiation A<T>* p2; // A<T> is not the current instantiation};
|
||
|
||
template <class T1, class T2, int I> struct B { B<T1, T2, I>* b1; // refers to the current instantiation B<T2, T1, I>* b2; // not the current instantiationtypedef 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; // refers to the current instantiation B<my_T1, T2, my_I2>* b4; // not the current instantiation B<my_T1, T2, my_I3>* b5; // refers to the current instantiation B<my_T1, T2, my_I4>* b6; // not the current instantiation B<my_T1, T2, my_I5>* b7; // not the current instantiation}; â *end example*]
|
||
|
||
[3](#temp.dep.type-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5446)
|
||
|
||
A [*dependent base class*](#def:base_class,dependent "13.8.3.2 Dependent types [temp.dep.type]") is a base class that is a dependent type and is
|
||
not the current instantiation[.](#temp.dep.type-3.sentence-1)
|
||
|
||
[*Note [2](#temp.dep.type-note-2)*:
|
||
|
||
A base class can be the current instantiation in the case of a nested class
|
||
naming an enclosing class as a base[.](#temp.dep.type-3.sentence-2)
|
||
|
||
[*Example [2](#temp.dep.type-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; // OK, A<T>::M}; â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[4](#temp.dep.type-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5470)
|
||
|
||
A qualified ([[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup")) or unqualified name is a[*member of the current instantiation*](#def:current_instantiation,member_of_the "13.8.3.2 Dependent types [temp.dep.type]") if
|
||
|
||
- [(4.1)](#temp.dep.type-4.1)
|
||
|
||
its lookup context, if it is a qualified name,
|
||
is the current instantiation, and
|
||
|
||
- [(4.2)](#temp.dep.type-4.2)
|
||
|
||
lookup for it finds any member of a class that is the current instantiation
|
||
|
||
[*Example [3](#temp.dep.type-example-3)*: template <class T> class A {static const int i = 5; int n1[i]; // i refers to a member of the current instantiationint n2[A::i]; // A::i refers to a member of the current instantiationint n3[A<T>::i]; // A<T>::i refers to a member of the current instantiationint f();};
|
||
|
||
template <class T> int A<T>::f() {return i; // i refers to a member of the current instantiation} â *end example*]
|
||
|
||
A qualified or unqualified name names a [*dependent member of the current instantiation*](#def:current_instantiation,dependent_member_of_the "13.8.3.2 Dependent types [temp.dep.type]") if it is a
|
||
member of the current instantiation that, when looked up, refers to at least
|
||
one member declaration
|
||
(including a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") whose terminal name is dependent)
|
||
of a class that is the current instantiation[.](#temp.dep.type-4.sentence-2)
|
||
|
||
[5](#temp.dep.type-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5505)
|
||
|
||
A qualified name ([[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup")) is dependent if
|
||
|
||
- [(5.1)](#temp.dep.type-5.1)
|
||
|
||
it is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") whose [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]") is dependent, or
|
||
|
||
- [(5.2)](#temp.dep.type-5.2)
|
||
|
||
its lookup context is dependent and is not the current instantiation, or
|
||
|
||
- [(5.3)](#temp.dep.type-5.3)
|
||
|
||
its lookup context is the current instantiation and
|
||
it is operator=,[117](#footnote-117 "Every instantiation of a class template declares a different set of assignment operators.") or
|
||
|
||
- [(5.4)](#temp.dep.type-5.4)
|
||
|
||
its lookup context is the current instantiation and
|
||
has at least one dependent base class, and
|
||
qualified name lookup for the name finds nothing ([[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup"))[.](#temp.dep.type-5.sentence-1)
|
||
|
||
[*Example [4](#temp.dep.type-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; // error: typename needed to interpret B as a type}template void g(C); // …even though A is ::A here â *end example*]
|
||
|
||
[6](#temp.dep.type-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5541)
|
||
|
||
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[.](#temp.dep.type-6.sentence-1)
|
||
|
||
If the result of this lookup differs from the
|
||
result of name lookup in the template definition context, name lookup is
|
||
ambiguous[.](#temp.dep.type-6.sentence-2)
|
||
|
||
[*Example [5](#temp.dep.type-example-5)*: struct A {int m;};
|
||
|
||
struct B {int m;};
|
||
|
||
template<typename T>struct C : A, T {int f() { return this->m; } // finds A::m in the template definition contextint g() { return m; } // finds A::m in the template definition context};
|
||
|
||
template int C<B>::f(); // error: finds both A::m and B::mtemplate int C<B>::g(); // OK, transformation to class member access syntax// does not occur in the template definition context; see [[expr.prim.id.general]](expr.prim.id.general "7.5.5.1 General") â *end example*]
|
||
|
||
[7](#temp.dep.type-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5570)
|
||
|
||
An initializer is dependent if
|
||
any constituent expression ([[intro.execution]](intro.execution "6.10.1 Sequential execution")) of the initializer
|
||
is type-dependent[.](#temp.dep.type-7.sentence-1)
|
||
|
||
A placeholder type ([[dcl.spec.auto.general]](dcl.spec.auto.general "9.2.9.7.1 General")) is dependent if
|
||
it designates a type deduced from a dependent initializer[.](#temp.dep.type-7.sentence-2)
|
||
|
||
[8](#temp.dep.type-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5577)
|
||
|
||
A placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced class template specialization types"))
|
||
is dependent if
|
||
|
||
- [(8.1)](#temp.dep.type-8.1)
|
||
|
||
it has a dependent initializer, or
|
||
|
||
- [(8.2)](#temp.dep.type-8.2)
|
||
|
||
it refers to an alias template
|
||
that is a member of the current instantiation and
|
||
whose [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]") is dependent after
|
||
class template argument deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9 Class template argument deduction"))
|
||
and substitution ([[temp.alias]](temp.alias "13.7.8 Alias templates"))[.](#temp.dep.type-8.sentence-1)
|
||
|
||
[9](#temp.dep.type-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5591)
|
||
|
||
[*Example [6](#temp.dep.type-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); // dependentnew Y(1); // not dependent}}; â *end example*]
|
||
|
||
[10](#temp.dep.type-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5609)
|
||
|
||
A type is dependent if it is
|
||
|
||
- [(10.1)](#temp.dep.type-10.1)
|
||
|
||
a template parameter,
|
||
|
||
- [(10.2)](#temp.dep.type-10.2)
|
||
|
||
denoted by a dependent (qualified) name,
|
||
|
||
- [(10.3)](#temp.dep.type-10.3)
|
||
|
||
a nested class or enumeration that is a direct member of
|
||
a class that is the current instantiation,
|
||
|
||
- [(10.4)](#temp.dep.type-10.4)
|
||
|
||
a cv-qualified type where the cv-unqualified type is dependent,
|
||
|
||
- [(10.5)](#temp.dep.type-10.5)
|
||
|
||
a compound type constructed from any dependent type,
|
||
|
||
- [(10.6)](#temp.dep.type-10.6)
|
||
|
||
an array type whose element type is dependent or whose
|
||
bound (if any) is value-dependent,
|
||
|
||
- [(10.7)](#temp.dep.type-10.7)
|
||
|
||
a function type whose parameters include one or more function parameter packs,
|
||
|
||
- [(10.8)](#temp.dep.type-10.8)
|
||
|
||
a function type whose exception specification is value-dependent,
|
||
|
||
- [(10.9)](#temp.dep.type-10.9)
|
||
|
||
denoted by a dependent placeholder type,
|
||
|
||
- [(10.10)](#temp.dep.type-10.10)
|
||
|
||
denoted by a dependent placeholder for a deduced class type,
|
||
|
||
- [(10.11)](#temp.dep.type-10.11)
|
||
|
||
denoted by a [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") in which either the template name is a template parameter or any of the
|
||
template arguments is dependent ([[temp.dep.temp]](#temp.dep.temp "13.8.3.7 Dependent template arguments")),[118](#footnote-118 "This includes an injected-class-name ([class.pre]) of a class template used without a template-argument-list.")
|
||
|
||
- [(10.12)](#temp.dep.type-10.12)
|
||
|
||
a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]"),
|
||
|
||
- [(10.13)](#temp.dep.type-10.13)
|
||
|
||
denoted by decltype([*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")),
|
||
where [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is [type-dependent](#temp.dep.expr "13.8.3.3 Type-dependent expressions [temp.dep.expr]"), or
|
||
|
||
- [(10.14)](#temp.dep.type-10.14)
|
||
|
||
denoted by a [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") in which either
|
||
the [*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]") is dependent ([[temp.dep.splice]](#temp.dep.splice "13.8.3.5 Dependent splice specifiers"))[.](#temp.dep.type-10.sentence-1)
|
||
|
||
[11](#temp.dep.type-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5651)
|
||
|
||
[*Note [3](#temp.dep.type-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[.](#temp.dep.type-11.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[117)](#footnote-117)[117)](#footnoteref-117)
|
||
|
||
Every instantiation of a class template declares
|
||
a different set of assignment operators[.](#footnote-117.sentence-1)
|
||
|
||
[118)](#footnote-118)[118)](#footnoteref-118)
|
||
|
||
This includes an injected-class-name ([[class.pre]](class.pre "11.1 Preamble")) of a class template
|
||
used without a [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]")[.](#footnote-118.sentence-1)
|
||
|
||
#### [13.8.3.3](#temp.dep.expr) Type-dependent expressions [[temp.dep.expr]](temp.dep.expr)
|
||
|
||
[1](#temp.dep.expr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5661)
|
||
|
||
Except as described below, an expression is type-dependent if any
|
||
subexpression is type-dependent[.](#temp.dep.expr-1.sentence-1)
|
||
|
||
[2](#temp.dep.expr-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5665)
|
||
|
||
this is type-dependent if the current class ([[expr.prim.this]](expr.prim.this "7.5.3 This")) is
|
||
dependent ([[temp.dep.type]](#temp.dep.type "13.8.3.2 Dependent types"))[.](#temp.dep.expr-2.sentence-1)
|
||
|
||
[3](#temp.dep.expr-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5670)
|
||
|
||
An [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is type-dependent
|
||
if it is a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") that is not a concept-id and is dependent;
|
||
or if its terminal name is
|
||
|
||
- [(3.1)](#temp.dep.expr-3.1)
|
||
|
||
associated by name lookup with one or more declarations
|
||
declared with a dependent type,
|
||
|
||
- [(3.2)](#temp.dep.expr-3.2)
|
||
|
||
associated by name lookup with
|
||
a constant template parameter
|
||
declared with a type
|
||
that contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")),
|
||
|
||
- [(3.3)](#temp.dep.expr-3.3)
|
||
|
||
associated by name lookup with
|
||
a variable declared with a type that contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))
|
||
where the initializer is type-dependent,
|
||
|
||
- [(3.4)](#temp.dep.expr-3.4)
|
||
|
||
associated by name lookup with one or more
|
||
declarations of member functions of a class that is the current instantiation
|
||
declared with a return type that contains a placeholder type,
|
||
|
||
- [(3.5)](#temp.dep.expr-3.5)
|
||
|
||
associated by name lookup with
|
||
a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations")) whose[*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") is type-dependent,
|
||
|
||
- [(3.6)](#temp.dep.expr-3.6)
|
||
|
||
associated by name lookup with a pack,
|
||
[*Example [1](#temp.dep.expr-example-1)*: struct C { };
|
||
|
||
void g(...); // #1template <typename T>void f() { C arr[1]; auto [...e] = arr;
|
||
g(e...); // calls #2}void g(C); // #2int main() { f<int>();} â *end example*]
|
||
|
||
- [(3.7)](#temp.dep.expr-3.7)
|
||
|
||
associated by name lookup with
|
||
an entity captured by copy ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3 Captures"))
|
||
in a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") that has an explicit object parameter whose type is dependent ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||
|
||
- [(3.8)](#temp.dep.expr-3.8)
|
||
|
||
the[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")__func__ ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General")), where any enclosing function is a
|
||
template, a member of a class template, or a generic lambda,
|
||
|
||
- [(3.9)](#temp.dep.expr-3.9)
|
||
|
||
associated by name lookup
|
||
with a result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2 Referring to the result object")) of a function
|
||
whose return type is dependent,
|
||
|
||
- [(3.10)](#temp.dep.expr-3.10)
|
||
|
||
a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") that specifies a dependent type,
|
||
|
||
- [(3.11)](#temp.dep.expr-3.11)
|
||
|
||
a name N introduced by the [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") of an expansion statement S if the type specified for N contains a placeholder type and either
|
||
* [(3.11.1)](#temp.dep.expr-3.11.1)
|
||
|
||
the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7 Expansion statements [stmt.expand]") of S is type-dependent or
|
||
|
||
* [(3.11.2)](#temp.dep.expr-3.11.2)
|
||
|
||
S is not an iterating expansion statement, or
|
||
|
||
- [(3.12)](#temp.dep.expr-3.12)
|
||
|
||
dependent
|
||
|
||
or if it names a dependent member of the current instantiation that is a static
|
||
data member of type
|
||
âarray of unknown bound of Tâ for some T ([[temp.static]](temp.static "13.7.2.5 Static data members of class templates"))[.](#temp.dep.expr-3.sentence-1)
|
||
|
||
Expressions of the following forms are type-dependent only if the type
|
||
specified by the[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]"),[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]"),[*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]"),
|
||
or[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") is dependent, even if any subexpression is type-dependent:
|
||
|
||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||
[*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||
[*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||
::opt new [*new-placement*](expr.new#nt:new-placement "7.6.2.8 New [expr.new]")opt [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]")opt
|
||
::opt new [*new-placement*](expr.new#nt:new-placement "7.6.2.8 New [expr.new]")opt ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]")opt
|
||
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
|
||
|
||
[4](#temp.dep.expr-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5769)
|
||
|
||
Expressions of the following forms are never type-dependent (because the type
|
||
of the expression cannot be dependent):
|
||
|
||
[*literal*](lex.literal.kinds#nt:literal "5.13.1 Kinds of literals [lex.literal.kinds]")
|
||
sizeof [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]")
|
||
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||
sizeof ... ( [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") )
|
||
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||
typeid ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||
::opt delete [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
|
||
::opt delete [ ] [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
|
||
throw [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")opt
|
||
noexcept ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
[*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]")
|
||
[*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]")
|
||
|
||
[*Note [1](#temp.dep.expr-note-1)*:
|
||
|
||
For the standard library macro offsetof,
|
||
see [[support.types]](support.types "17.2 Common definitions")[.](#temp.dep.expr-4.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[5](#temp.dep.expr-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5793)
|
||
|
||
A [class member access expression](expr.ref "7.6.1.5 Class member access [expr.ref]") is
|
||
type-dependent if
|
||
the terminal name of its [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]"), if any, is dependent or
|
||
the expression refers to a member of the current instantiation and
|
||
the type of the referenced member is dependent[.](#temp.dep.expr-5.sentence-1)
|
||
|
||
[*Note [2](#temp.dep.expr-note-2)*:
|
||
|
||
In an expression of the formx.y orxp->y the type of the expression is usually the type of the membery of the class ofx (or the class pointed to byxp)[.](#temp.dep.expr-5.sentence-2)
|
||
|
||
However, ifx orxp refers to a dependent type that is not the current instantiation,
|
||
the type ofy is always dependent[.](#temp.dep.expr-5.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[6](#temp.dep.expr-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5820)
|
||
|
||
A [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") is type-dependent if any element is
|
||
type-dependent or is a pack expansion[.](#temp.dep.expr-6.sentence-1)
|
||
|
||
[7](#temp.dep.expr-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5824)
|
||
|
||
A [*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7 Fold expressions [expr.prim.fold]") is type-dependent[.](#temp.dep.expr-7.sentence-1)
|
||
|
||
[8](#temp.dep.expr-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5827)
|
||
|
||
A [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4 Pack indexing expression [expr.prim.pack.index]") is type-dependent
|
||
if its [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is type-dependent[.](#temp.dep.expr-8.sentence-1)
|
||
|
||
[9](#temp.dep.expr-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5831)
|
||
|
||
A [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") is type-dependent
|
||
if its [*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]") is dependent ([[temp.dep.splice]](#temp.dep.splice "13.8.3.5 Dependent splice specifiers"))[.](#temp.dep.expr-9.sentence-1)
|
||
|
||
#### [13.8.3.4](#temp.dep.constexpr) Value-dependent expressions [[temp.dep.constexpr]](temp.dep.constexpr)
|
||
|
||
[1](#temp.dep.constexpr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5839)
|
||
|
||
Except as described below, an expression used in a context where a
|
||
constant expression is required is value-dependent if any
|
||
subexpression is value-dependent[.](#temp.dep.constexpr-1.sentence-1)
|
||
|
||
[2](#temp.dep.constexpr-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5844)
|
||
|
||
An[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is value-dependent if
|
||
|
||
- [(2.1)](#temp.dep.constexpr-2.1)
|
||
|
||
it is a concept-id and
|
||
its [*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]") is dependent or
|
||
any of its arguments are dependent ([[temp.dep.temp]](#temp.dep.temp "13.8.3.7 Dependent template arguments")),
|
||
|
||
- [(2.2)](#temp.dep.constexpr-2.2)
|
||
|
||
it is type-dependent,
|
||
|
||
- [(2.3)](#temp.dep.constexpr-2.3)
|
||
|
||
it is the name of a constant template parameter,
|
||
|
||
- [(2.4)](#temp.dep.constexpr-2.4)
|
||
|
||
it is a name introduced by the [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1 Preamble [stmt.pre]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion statements")),
|
||
|
||
- [(2.5)](#temp.dep.constexpr-2.5)
|
||
|
||
it names a static data member that is a dependent member of the current
|
||
instantiation and is not initialized in a [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]"),
|
||
|
||
- [(2.6)](#temp.dep.constexpr-2.6)
|
||
|
||
it names a static member function that is a dependent member of the current
|
||
instantiation, or
|
||
|
||
- [(2.7)](#temp.dep.constexpr-2.7)
|
||
|
||
it names a potentially-constant variable ([[expr.const]](expr.const "7.7 Constant expressions"))
|
||
that is initialized with an expression that is value-dependent[.](#temp.dep.constexpr-2.sentence-1)
|
||
|
||
Expressions of the following form are value-dependent if the[*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]") or [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is type-dependent or the[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") is dependent:
|
||
|
||
sizeof [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]")
|
||
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||
typeid ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||
|
||
[*Note [1](#temp.dep.constexpr-note-1)*:
|
||
|
||
For the standard library macro offsetof,
|
||
see [[support.types]](support.types "17.2 Common definitions")[.](#temp.dep.constexpr-2.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[3](#temp.dep.constexpr-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5889)
|
||
|
||
Expressions of the following form are value-dependent if either the[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]"),[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]"), or[*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]") is dependent or the[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") or[*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") is value-dependent or
|
||
any [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") is value-dependent or
|
||
any [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") in the [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") is value-dependent:
|
||
|
||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||
[*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||
[*typename-specifier*](#nt:typename-specifier "13.8.1 General [temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||
( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
|
||
|
||
[4](#temp.dep.constexpr-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5915)
|
||
|
||
Expressions of the following form are value-dependent:
|
||
|
||
sizeof ... ( [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") )
|
||
[*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7 Fold expressions [expr.prim.fold]")
|
||
|
||
unless the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is a structured binding pack
|
||
whose initializer is not dependent[.](#temp.dep.constexpr-4.sentence-1)
|
||
|
||
[5](#temp.dep.constexpr-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5924)
|
||
|
||
A [*noexcept-expression*](expr.unary.noexcept#nt:noexcept-expression "7.6.2.7 noexcept operator [expr.unary.noexcept]") ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7 noexcept operator"))
|
||
is value-dependent if
|
||
its [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") involves a template parameter[.](#temp.dep.constexpr-5.sentence-1)
|
||
|
||
[6](#temp.dep.constexpr-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5929)
|
||
|
||
An expression of the form &[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") where the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") names a dependent member of the current
|
||
instantiation is value-dependent[.](#temp.dep.constexpr-6.sentence-1)
|
||
|
||
An expression of the form &[*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") is also value-dependent if evaluating [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") as a [core constant expression](expr.const#def:expression,core_constant "7.7 Constant expressions [expr.const]") succeeds and
|
||
the result of the evaluation refers to a templated entity
|
||
that is an object with static or thread storage duration or a member function[.](#temp.dep.constexpr-6.sentence-2)
|
||
|
||
[7](#temp.dep.constexpr-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5939)
|
||
|
||
A [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") is value-dependent if
|
||
|
||
- [(7.1)](#temp.dep.constexpr-7.1)
|
||
|
||
it is of the form ^^[*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]") and
|
||
the [*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]")
|
||
* [(7.1.1)](#temp.dep.constexpr-7.1.1)
|
||
|
||
is a dependent qualified name,
|
||
|
||
* [(7.1.2)](#temp.dep.constexpr-7.1.2)
|
||
|
||
is a dependent [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]"),
|
||
|
||
* [(7.1.3)](#temp.dep.constexpr-7.1.3)
|
||
|
||
is the name of a template parameter, or
|
||
|
||
* [(7.1.4)](#temp.dep.constexpr-7.1.4)
|
||
|
||
names a dependent member of the current instantiation ([[temp.dep.type]](#temp.dep.type "13.8.3.2 Dependent types")),
|
||
|
||
- [(7.2)](#temp.dep.constexpr-7.2)
|
||
|
||
it is of the form ^^[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") and
|
||
the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") denotes a dependent type, or
|
||
|
||
- [(7.3)](#temp.dep.constexpr-7.3)
|
||
|
||
it is of the form ^^[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") and
|
||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is value-dependent[.](#temp.dep.constexpr-7.sentence-1)
|
||
|
||
[8](#temp.dep.constexpr-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5959)
|
||
|
||
A [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") is value-dependent
|
||
if its [*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]") is dependent ([[temp.dep.splice]](#temp.dep.splice "13.8.3.5 Dependent splice specifiers"))[.](#temp.dep.constexpr-8.sentence-1)
|
||
|
||
#### [13.8.3.5](#temp.dep.splice) Dependent splice specifiers [[temp.dep.splice]](temp.dep.splice)
|
||
|
||
[1](#temp.dep.splice-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5967)
|
||
|
||
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") is dependent
|
||
if its converted [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is value-dependent[.](#temp.dep.splice-1.sentence-1)
|
||
|
||
A [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is dependent
|
||
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") is dependent or
|
||
if any of its template arguments are dependent[.](#temp.dep.splice-1.sentence-2)
|
||
|
||
A [*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") is dependent
|
||
if its [*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]") is dependent[.](#temp.dep.splice-1.sentence-3)
|
||
|
||
[2](#temp.dep.splice-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5977)
|
||
|
||
[*Example [1](#temp.dep.splice-example-1)*: template<auto T, auto NS>void fn() {using a = [:T:]<1>; // [:T:]<1> is dependent because [:T:] is dependentstatic_assert([:NS:]::template TCls<1>::v == a::v); // [:NS:] is dependent}namespace N {template <auto V> struct TCls { static constexpr int v = V; };}int main() { fn<^^N::TCls, ^^N>();} â *end example*]
|
||
|
||
[3](#temp.dep.splice-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5996)
|
||
|
||
[*Example [2](#temp.dep.splice-example-2)*: template<template<class> class X>struct S {[:^^X:]<int, float> m;};
|
||
|
||
template<class> struct V1 {};template<class, class = int> struct V2 {};
|
||
|
||
S<V1> s1; // error: V1<int, float> has too many template arguments S<V2> s2; // OK â *end example*]
|
||
|
||
#### [13.8.3.6](#temp.dep.namespace) Dependent namespaces [[temp.dep.namespace]](temp.dep.namespace)
|
||
|
||
[1](#temp.dep.namespace-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6014)
|
||
|
||
A namespace alias is dependent
|
||
if it is introduced by a [*namespace-alias-definition*](namespace.alias#nt:namespace-alias-definition "9.9.3 Namespace alias [namespace.alias]") whose [*qualified-namespace-specifier*](namespace.alias#nt:qualified-namespace-specifier "9.9.3 Namespace alias [namespace.alias]") (if any) is
|
||
a dependent qualified name or
|
||
whose [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") (if any) is dependent[.](#temp.dep.namespace-1.sentence-1)
|
||
|
||
A [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]") is dependent
|
||
if it names a dependent namespace alias[.](#temp.dep.namespace-1.sentence-2)
|
||
|
||
[2](#temp.dep.namespace-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6023)
|
||
|
||
[*Example [1](#temp.dep.namespace-example-1)*: template<std::meta::info R>int fn() {namespace Alias = [:R:]; // [:R:] is dependentreturn typename Alias::T{}; // Alias is dependent}namespace NS {using T = int;}int a = fn<^^NS>(); â *end example*]
|
||
|
||
#### [13.8.3.7](#temp.dep.temp) Dependent template arguments [[temp.dep.temp]](temp.dep.temp)
|
||
|
||
[1](#temp.dep.temp-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6042)
|
||
|
||
A type[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") is dependent if the type it specifies is dependent[.](#temp.dep.temp-1.sentence-1)
|
||
|
||
[2](#temp.dep.temp-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6047)
|
||
|
||
A constant[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") is dependent if its type is dependent or the constant
|
||
expression it specifies is value-dependent[.](#temp.dep.temp-2.sentence-1)
|
||
|
||
[3](#temp.dep.temp-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6053)
|
||
|
||
Furthermore, a constant[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") is dependent if the corresponding constant template parameter
|
||
is of reference or pointer type and the [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") designates or points to a member of the current instantiation or a member of
|
||
a dependent type[.](#temp.dep.temp-3.sentence-1)
|
||
|
||
[4](#temp.dep.temp-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6061)
|
||
|
||
A template argument is also dependent if it is a pack expansion[.](#temp.dep.temp-4.sentence-1)
|
||
|
||
[5](#temp.dep.temp-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6065)
|
||
|
||
A template template parameter is dependent if
|
||
it names a template parameter or
|
||
its terminal name is dependent[.](#temp.dep.temp-5.sentence-1)
|
||
|
||
### [13.8.4](#temp.dep.res) Dependent name resolution [[temp.dep.res]](temp.dep.res)
|
||
|
||
#### [13.8.4.1](#temp.point) Point of instantiation [[temp.point]](temp.point)
|
||
|
||
[1](#temp.point-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6073)
|
||
|
||
For a function template specialization, a member function template
|
||
specialization, or a specialization for a member function or static data member
|
||
of a class template,
|
||
if the specialization is implicitly instantiated because it is referenced
|
||
from within another template specialization and
|
||
the context from which it is referenced depends on a template parameter,
|
||
the point of instantiation of the specialization is the point of instantiation
|
||
of the enclosing specialization[.](#temp.point-1.sentence-1)
|
||
|
||
Otherwise, the point of instantiation for such a specialization immediately
|
||
follows the namespace scope declaration
|
||
or definition that refers to the specialization[.](#temp.point-1.sentence-2)
|
||
|
||
[2](#temp.point-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6087)
|
||
|
||
If a function template or member function of a class template is called
|
||
in a way which uses the definition of a default argument of that function
|
||
template or member function,
|
||
the point of instantiation of the default argument is the point of
|
||
instantiation of the function template or member function specialization[.](#temp.point-2.sentence-1)
|
||
|
||
[3](#temp.point-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6094)
|
||
|
||
For a [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") of a function template
|
||
specialization or specialization of a member function of a class template, if
|
||
the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") is implicitly instantiated because
|
||
it is needed by another template specialization and the context that requires
|
||
it depends on a template parameter, the point of instantiation of the[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") is the point of instantiation of the
|
||
specialization that requires it[.](#temp.point-3.sentence-1)
|
||
|
||
Otherwise, the point of instantiation for such
|
||
a [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") immediately follows the namespace
|
||
scope declaration or definition that requires the[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")[.](#temp.point-3.sentence-2)
|
||
|
||
[4](#temp.point-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6106)
|
||
|
||
For a class template specialization, a class member template specialization,
|
||
or a specialization for a class member of a class template,
|
||
if the specialization is implicitly instantiated because it is referenced
|
||
from within another template specialization,
|
||
if the context from which the specialization is referenced depends on a
|
||
template parameter,
|
||
and if the specialization is not instantiated previous to the instantiation of
|
||
the enclosing template,
|
||
the point of instantiation is immediately before the point of instantiation of
|
||
the enclosing template[.](#temp.point-4.sentence-1)
|
||
|
||
Otherwise, the point of instantiation for such a specialization immediately
|
||
precedes the namespace scope declaration
|
||
or definition that refers to the specialization[.](#temp.point-4.sentence-2)
|
||
|
||
[5](#temp.point-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6121)
|
||
|
||
If a virtual function is implicitly instantiated, its point of instantiation
|
||
is immediately following the point of instantiation of its enclosing class
|
||
template specialization[.](#temp.point-5.sentence-1)
|
||
|
||
[6](#temp.point-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6126)
|
||
|
||
An explicit instantiation definition is an instantiation
|
||
point for the specialization or specializations specified by the explicit
|
||
instantiation[.](#temp.point-6.sentence-1)
|
||
|
||
[7](#temp.point-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6131)
|
||
|
||
A specialization for a function template, a member function template,
|
||
or of a member function or static data member of a class template may have
|
||
multiple points of instantiations within a translation unit, and in addition
|
||
to the points of instantiation described above,
|
||
|
||
- [(7.1)](#temp.point-7.1)
|
||
|
||
for any such
|
||
specialization that has a point of instantiation within the[*declaration-seq*](dcl.pre#nt:declaration-seq "9.1 Preamble [dcl.pre]") of the[*translation-unit*](basic.link#nt:translation-unit "6.7 Program and linkage [basic.link]"),
|
||
prior to the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]") (if any),
|
||
the point after the [*declaration-seq*](dcl.pre#nt:declaration-seq "9.1 Preamble [dcl.pre]") of the [*translation-unit*](basic.link#nt:translation-unit "6.7 Program and linkage [basic.link]") is also considered a point of instantiation,
|
||
and
|
||
|
||
- [(7.2)](#temp.point-7.2)
|
||
|
||
for any such specialization that has a point of instantiation
|
||
within the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]"),
|
||
the end of the translation unit is also
|
||
considered a point of instantiation[.](#temp.point-7.sentence-1)
|
||
|
||
A specialization for a class template has at most one point of instantiation
|
||
within a translation unit[.](#temp.point-7.sentence-2)
|
||
|
||
A specialization for any template may have points of instantiation in multiple
|
||
translation units[.](#temp.point-7.sentence-3)
|
||
|
||
If two different points of instantiation give a template specialization
|
||
different meanings according to the [one-definition rule](basic.def.odr "6.3 One-definition rule [basic.def.odr]"),
|
||
the program is ill-formed, no diagnostic required[.](#temp.point-7.sentence-4)
|
||
|
||
[8](#temp.point-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6161)
|
||
|
||
For the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion statements")),
|
||
the point of instantiation is the point of instantiation
|
||
of its enclosing templated entity, if any[.](#temp.point-8.sentence-1)
|
||
|
||
Otherwise, it immediately follows the namespace-scope declaration
|
||
or definition that contains the expansion statement[.](#temp.point-8.sentence-2)
|
||
|
||
#### [13.8.4.2](#temp.dep.candidate) Candidate functions [[temp.dep.candidate]](temp.dep.candidate)
|
||
|
||
[1](#temp.dep.candidate-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6171)
|
||
|
||
If a dependent call ([[temp.dep]](#temp.dep "13.8.3 Dependent names")) would be ill-formed or
|
||
would find a better match had the lookup for its dependent name
|
||
considered all the function declarations with external linkage
|
||
introduced in the associated namespaces in all translation units,
|
||
not just considering those declarations found in the template definition and
|
||
template instantiation contexts ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup")),
|
||
then the program is ill-formed, no diagnostic required[.](#temp.dep.candidate-1.sentence-1)
|
||
|
||
[2](#temp.dep.candidate-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6181)
|
||
|
||
[*Example [1](#temp.dep.candidate-example-1)*:
|
||
|
||
Source file "X.h":namespace Q {struct X { };}
|
||
|
||
Source file "G.h":namespace Q {void g_impl(X, X);}
|
||
|
||
Module interface unit of M1:module;#include "X.h"#include "G.h"export module M1;export template<typename T>void g(T t) { g_impl(t, Q::X{ }); // ADL in definition context finds Q::g_impl, g_impl not discarded}
|
||
|
||
Module interface unit of M2:module;#include "X.h"export module M2;import M1;void h(Q::X x) { g(x); // OK} â *end example*]
|
||
|
||
[3](#temp.dep.candidate-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6217)
|
||
|
||
[*Example [2](#temp.dep.candidate-example-2)*:
|
||
|
||
Module interface unit of Std:export module Std;export template<typename Iter>void indirect_swap(Iter lhs, Iter rhs){ swap(*lhs, *rhs); // swap not found by unqualified lookup, can be found only via ADL}
|
||
|
||
Module interface unit of M:export module M;import Std;
|
||
|
||
struct S { /* ...*/ };void swap(S&, S&); // #1void f(S* p, S* q){ indirect_swap(p, q); // finds #1 via ADL in instantiation context} â *end example*]
|
||
|
||
[4](#temp.dep.candidate-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6242)
|
||
|
||
[*Example [3](#temp.dep.candidate-example-3)*:
|
||
|
||
Source file "X.h":struct X { /* ... */ };
|
||
X operator+(X, X);
|
||
|
||
Module interface unit of F:export module F;export template<typename T>void f(T t) { t + t;}
|
||
|
||
Module interface unit of M:module;#include "X.h"export module M;import F;void g(X x) { f(x); // OK, instantiates f from F,// operator+ is visible in instantiation context} â *end example*]
|
||
|
||
[5](#temp.dep.candidate-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6269)
|
||
|
||
[*Example [4](#temp.dep.candidate-example-4)*:
|
||
|
||
Module interface unit of A:export module A;export template<typename T>void f(T t) { cat(t, t); // #1 dog(t, t); // #2}
|
||
|
||
Module interface unit of B:export module B;import A;export template<typename T, typename U>void g(T t, U u) { f(t);}
|
||
|
||
Source file "foo.h", not an importable header:struct foo {friend int cat(foo, foo);};int dog(foo, foo);
|
||
|
||
Module interface unit of C1:module;#include "foo.h" // dog not referenced, discardedexport module C1;import B;export template<typename T>void h(T t) { g(foo{ }, t);}
|
||
|
||
Translation unit:import C1;void i() { h(0); // error: dog not found at #2}
|
||
|
||
Importable header "bar.h":struct bar {friend int cat(bar, bar);};int dog(bar, bar);
|
||
|
||
Module interface unit of C2:module;#include "bar.h" // imports header unit "bar.h"export module C2;import B;export template<typename T>void j(T t) { g(bar{ }, t);}
|
||
|
||
Translation unit:import C2;void k() { j(0); // OK, dog found in instantiation context:// visible at end of module interface unit of C2} â *end example*]
|