Init
This commit is contained in:
87
cppdraft/temp/constr/atomic.md
Normal file
87
cppdraft/temp/constr/atomic.md
Normal file
@@ -0,0 +1,87 @@
|
||||
[temp.constr.atomic]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.5 Template constraints [[temp.constr]](temp.constr#atomic)
|
||||
|
||||
### 13.5.2 Constraints [[temp.constr.constr]](temp.constr.constr#temp.constr.atomic)
|
||||
|
||||
#### 13.5.2.3 Atomic constraints [temp.constr.atomic]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1738)
|
||||
|
||||
An [*atomic constraint*](#def:constraint,atomic "13.5.2.3 Atomic constraints [temp.constr.atomic]") is formed from
|
||||
an expression E and a mapping from the template parameters
|
||||
that appear within E to
|
||||
template arguments that are formed via substitution during constraint normalization
|
||||
in the declaration of a constrained entity (and, therefore, can involve the
|
||||
unsubstituted template parameters of the constrained entity),
|
||||
called the [*parameter mapping*](#def:parameter_mapping "13.5.2.3 Atomic constraints [temp.constr.atomic]") ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations"))[.](#1.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Atomic constraints are formed by [constraint normalization](temp.constr.normal#def:constraint,normalization "13.5.4 Constraint normalization [temp.constr.normal]")[.](#1.sentence-2)
|
||||
|
||||
E is never a [logical and expression](expr.log.and "7.6.14 Logical AND operator [expr.log.and]") nor a [logical or expression](expr.log.or "7.6.15 Logical OR operator [expr.log.or]")[.](#1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1753)
|
||||
|
||||
Two atomic constraints, e1 and e2, are[*identical*](#def:atomic_constraint,identical "13.5.2.3 Atomic constraints [temp.constr.atomic]") if they are formed from the same appearance of the same[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") and if, given a hypothetical template A whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") consists of[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* corresponding and equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) to
|
||||
those mapped by the parameter mappings of the expression,
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are
|
||||
the targets of the parameter mapping of e1 is the same ([[temp.type]](temp.type "13.6 Type equivalence")) as
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are
|
||||
the targets of the parameter mapping of e2[.](#2.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
The comparison of parameter mappings of atomic constraints
|
||||
operates in a manner similar to that of declaration matching
|
||||
with alias template substitution ([[temp.alias]](temp.alias "13.7.8 Alias templates"))[.](#2.sentence-2)
|
||||
|
||||
[*Example [1](#example-1)*: template <unsigned N> constexpr bool Atomic = true;template <unsigned N> concept C = Atomic<N>;template <unsigned N> concept Add1 = C<N + 1>;template <unsigned N> concept AddOne = C<N + 1>;template <unsigned M> void f()requires Add1<2 * M>;template <unsigned M> int f()requires AddOne<2 * M> && true;
|
||||
|
||||
int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic<N>// with mapping similar to Nâ¦2 * M + 1template <unsigned N> struct WrapN;template <unsigned N> using Add1Ty = WrapN<N + 1>;template <unsigned N> using AddOneTy = WrapN<N + 1>;template <unsigned M> void g(Add1Ty<2 * M> *);template <unsigned M> void g(AddOneTy<2 * M> *);
|
||||
|
||||
void h() { g<0>(nullptr); // OK, there is only one g} â *end example*]
|
||||
|
||||
As specified in [[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"),
|
||||
if the validity or meaning of the program depends on
|
||||
whether two constructs are equivalent, and
|
||||
they are functionally equivalent but not equivalent,
|
||||
the program is ill-formed, no diagnostic required[.](#2.sentence-3)
|
||||
|
||||
[*Example [2](#example-2)*: template <unsigned N> void f2()requires Add1<2 * N>;template <unsigned N> int f2()requires Add1<N * 2> && true;void h2() { f2<0>(); // ill-formed, no diagnostic required:// requires determination of subsumption between atomic constraints that are// functionally equivalent but not equivalent} â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1819)
|
||||
|
||||
To determine if an atomic constraint is[*satisfied*](#def:constraint,satisfaction,atomic "13.5.2.3 Atomic constraints [temp.constr.atomic]"),
|
||||
the parameter mapping and template arguments are
|
||||
first substituted into its expression[.](#3.sentence-1)
|
||||
|
||||
If substitution results in an invalid type or expression
|
||||
in the immediate context of the atomic constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1 General")),
|
||||
the constraint is not satisfied[.](#3.sentence-2)
|
||||
|
||||
Otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2 Lvalue-to-rvalue conversion [conv.lval]") is performed if necessary,
|
||||
and E shall be a constant expression of type bool[.](#3.sentence-3)
|
||||
|
||||
The constraint is satisfied if and only if evaluation of E results in true[.](#3.sentence-4)
|
||||
|
||||
If, at different points in the program, the satisfaction result is different
|
||||
for identical atomic constraints and template arguments,
|
||||
the program is ill-formed, no diagnostic required[.](#3.sentence-5)
|
||||
|
||||
[*Example [3](#example-3)*: template<typename T> concept C =sizeof(T) == 4 && !true; // requires atomic constraints sizeof(T) == 4 and !truetemplate<typename T> struct S {constexpr operator bool() const { return true; }};
|
||||
|
||||
template<typename T> requires (S<T>{})void f(T); // #1void f(int); // #2void g() { f(0); // error: expression S<int>{} does not have type bool} // while checking satisfaction of deduced arguments of #1;// call is ill-formed even though #2 is a better match â *end example*]
|
||||
81
cppdraft/temp/constr/concept.md
Normal file
81
cppdraft/temp/constr/concept.md
Normal file
@@ -0,0 +1,81 @@
|
||||
[temp.constr.concept]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.5 Template constraints [[temp.constr]](temp.constr#concept)
|
||||
|
||||
### 13.5.2 Constraints [[temp.constr.constr]](temp.constr.constr#temp.constr.concept)
|
||||
|
||||
#### 13.5.2.4 Concept-dependent constraints [temp.constr.concept]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1857)
|
||||
|
||||
A [*concept-dependent constraint*](#def:constraint,concept-dependent "13.5.2.4 Concept-dependent constraints [temp.constr.concept]") CD is
|
||||
an atomic constraint whose expression is a concept-id CI whose[*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]") names a dependent concept named C[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1862)
|
||||
|
||||
To determine if CD is[*satisfied*](#def:constraint,satisfaction,concept-dependent "13.5.2.4 Concept-dependent constraints [temp.constr.concept]"),
|
||||
the parameter mapping and template arguments are first
|
||||
substituted into C[.](#2.sentence-1)
|
||||
|
||||
If substitution results in an invalid concept-id in
|
||||
the immediate context of the constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1 General")),
|
||||
the constraint is not satisfied[.](#2.sentence-2)
|
||||
|
||||
Otherwise, let CIâ² be
|
||||
the normal form ([[temp.constr.normal]](temp.constr.normal "13.5.4 Constraint normalization")) of the concept-id
|
||||
after substitution of C[.](#2.sentence-3)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Normalization of CI might be ill-formed; no diagnostics is required[.](#2.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1877)
|
||||
|
||||
To form CIâ²â²,
|
||||
each appearance of C's template parameters in
|
||||
the parameter mappings of the atomic constraints
|
||||
(including concept-dependent constraints)
|
||||
in CIâ² is substituted with their respective arguments from
|
||||
the parameter mapping of CD and the arguments of CI[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1886)
|
||||
|
||||
CD is satisfied if CIâ²â² is satisfied[.](#4.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
Checking whether CIâ²â² is satisfied
|
||||
can lead to further normalization of concept-dependent constraints[.](#4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#example-1)*: template<typename>concept C = true;
|
||||
|
||||
template<typename T, template<typename> concept CC>concept D = CC<T>;
|
||||
|
||||
template<typename U, template<typename> concept CT, template<typename, template<typename> concept> concept CU>int f() requires CU<U, CT>;int i = f<int, C, D>();
|
||||
|
||||
In this example, the associated constraints of f consist of a concept-dependent constraint
|
||||
whose expression is the concept-id CU<U, CT> with the mappingUâ¦U,CTâ¦CT,CUâ¦CU[.](#4.sentence-3)
|
||||
|
||||
The result of substituting D into this expression is D<U, CT>[.](#4.sentence-4)
|
||||
|
||||
We consider the normal form of the resulting concept-id,
|
||||
which is CC<T> with the mappingTâ¦U,CCâ¦CT[.](#4.sentence-5)
|
||||
|
||||
By recursion, C is substituted into CC<T>, and the result
|
||||
is normalized to the atomic constraint true, which is satisfied[.](#4.sentence-6)
|
||||
|
||||
â *end example*]
|
||||
368
cppdraft/temp/constr/constr.md
Normal file
368
cppdraft/temp/constr/constr.md
Normal file
@@ -0,0 +1,368 @@
|
||||
[temp.constr.constr]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.5 Template constraints [[temp.constr]](temp.constr#constr)
|
||||
|
||||
### 13.5.2 Constraints [temp.constr.constr]
|
||||
|
||||
#### [13.5.2.1](#general) General [[temp.constr.constr.general]](temp.constr.constr.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1610)
|
||||
|
||||
A [*constraint*](#def:constraint "13.5.2.1 General [temp.constr.constr.general]") is a sequence of logical operations and
|
||||
operands that specifies requirements on template arguments[.](#general-1.sentence-1)
|
||||
|
||||
The operands of a logical operation are constraints[.](#general-1.sentence-2)
|
||||
|
||||
There are five different kinds of constraints:
|
||||
|
||||
- [(1.1)](#general-1.1)
|
||||
|
||||
conjunctions ([[temp.constr.op]](#temp.constr.op "13.5.2.2 Logical operations")),
|
||||
|
||||
- [(1.2)](#general-1.2)
|
||||
|
||||
disjunctions ([[temp.constr.op]](#temp.constr.op "13.5.2.2 Logical operations")),
|
||||
|
||||
- [(1.3)](#general-1.3)
|
||||
|
||||
atomic constraints ([[temp.constr.atomic]](#temp.constr.atomic "13.5.2.3 Atomic constraints")),
|
||||
|
||||
- [(1.4)](#general-1.4)
|
||||
|
||||
concept-dependent constraints ([[temp.constr.concept]](#temp.constr.concept "13.5.2.4 Concept-dependent constraints")), and
|
||||
|
||||
- [(1.5)](#general-1.5)
|
||||
|
||||
fold expanded constraints ([[temp.constr.fold]](#temp.constr.fold "13.5.2.5 Fold expanded constraint"))[.](#general-1.sentence-3)
|
||||
|
||||
[2](#general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1623)
|
||||
|
||||
In order for a constrained template to be instantiated ([[temp.spec]](temp.spec "13.9 Template instantiation and specialization")),
|
||||
its [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3 Constrained declarations [temp.constr.decl]") shall be satisfied as described in the following subclauses[.](#general-2.sentence-1)
|
||||
|
||||
[*Note [1](#general-note-1)*:
|
||||
|
||||
Forming the name of a specialization of
|
||||
a class template,
|
||||
a variable template, or
|
||||
an alias template ([[temp.names]](temp.names "13.3 Names of template specializations"))
|
||||
requires the satisfaction of its constraints[.](#general-2.sentence-2)
|
||||
|
||||
[Overload resolution](over.match.viable "12.2.3 Viable functions [over.match.viable]") requires the satisfaction of constraints
|
||||
on functions and function templates[.](#general-2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
#### [13.5.2.2](#temp.constr.op) Logical operations [[temp.constr.op]](temp.constr.op)
|
||||
|
||||
[1](#temp.constr.op-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1640)
|
||||
|
||||
There are two binary logical operations on constraints: conjunction
|
||||
and disjunction[.](#temp.constr.op-1.sentence-1)
|
||||
|
||||
[*Note [1](#temp.constr.op-note-1)*:
|
||||
|
||||
These logical operations have no corresponding C++ syntax[.](#temp.constr.op-1.sentence-2)
|
||||
|
||||
For the purpose of exposition, conjunction is spelled
|
||||
using the symbol â§ and disjunction is spelled using the
|
||||
symbol ⨠[.](#temp.constr.op-1.sentence-3)
|
||||
|
||||
The operands of these operations are called the left
|
||||
and right operands[.](#temp.constr.op-1.sentence-4)
|
||||
|
||||
In the constraint A â§ B,A is the left operand, and B is the right operand[.](#temp.constr.op-1.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#temp.constr.op-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1653)
|
||||
|
||||
A [*conjunction*](#def:conjunction "13.5.2.2 Logical operations [temp.constr.op]") is a constraint taking two
|
||||
operands[.](#temp.constr.op-2.sentence-1)
|
||||
|
||||
To determine if a conjunction is[*satisfied*](#def:constraint,satisfaction,conjunction "13.5.2.2 Logical operations [temp.constr.op]"),
|
||||
the satisfaction of
|
||||
the first operand is checked[.](#temp.constr.op-2.sentence-2)
|
||||
|
||||
If that is not satisfied, the conjunction is not satisfied[.](#temp.constr.op-2.sentence-3)
|
||||
|
||||
Otherwise, the conjunction is satisfied if and only if the second
|
||||
operand is satisfied[.](#temp.constr.op-2.sentence-4)
|
||||
|
||||
[3](#temp.constr.op-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1664)
|
||||
|
||||
A [*disjunction*](#def:disjunction "13.5.2.2 Logical operations [temp.constr.op]") is a constraint taking two
|
||||
operands[.](#temp.constr.op-3.sentence-1)
|
||||
|
||||
To determine if a disjunction is[*satisfied*](#def:constraint,satisfaction,disjunction "13.5.2.2 Logical operations [temp.constr.op]"),
|
||||
the satisfaction of
|
||||
the first operand is checked[.](#temp.constr.op-3.sentence-2)
|
||||
|
||||
If that is satisfied, the disjunction is satisfied[.](#temp.constr.op-3.sentence-3)
|
||||
|
||||
Otherwise, the disjunction is satisfied if and only if the second
|
||||
operand is satisfied[.](#temp.constr.op-3.sentence-4)
|
||||
|
||||
[4](#temp.constr.op-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1676)
|
||||
|
||||
[*Example [1](#temp.constr.op-example-1)*: template<typename T>constexpr bool get_value() { return T::value; }template<typename T>requires (sizeof(T) > 1) && (get_value<T>())void f(T); // has associated constraint sizeof(T) > 1 â§ get_value<T>()void f(int);
|
||||
|
||||
f('a'); // OK, calls f(int)
|
||||
|
||||
In the satisfaction of the [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3 Constrained declarations [temp.constr.decl]") of f, the constraint sizeof(char) > 1 is not satisfied;
|
||||
the second operand is not checked for satisfaction[.](#temp.constr.op-4.sentence-1)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[5](#temp.constr.op-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1695)
|
||||
|
||||
[*Note [2](#temp.constr.op-note-2)*:
|
||||
|
||||
A logical negation expression ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators")) is an atomic constraint;
|
||||
the negation operator is not treated as a logical operation on constraints[.](#temp.constr.op-5.sentence-1)
|
||||
|
||||
As a result, distinct negation [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* that are equivalent under [[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading") do not subsume one another under [[temp.constr.order]](temp.constr.order "13.5.5 Partial ordering by constraints")[.](#temp.constr.op-5.sentence-2)
|
||||
|
||||
Furthermore, if substitution to determine
|
||||
whether an atomic constraint is satisfied ([[temp.constr.atomic]](#temp.constr.atomic "13.5.2.3 Atomic constraints"))
|
||||
encounters a substitution failure, the constraint is not satisfied,
|
||||
regardless of the presence of a negation operator[.](#temp.constr.op-5.sentence-3)
|
||||
|
||||
[*Example [2](#temp.constr.op-example-2)*: template <class T> concept sad = false;
|
||||
|
||||
template <class T> int f1(T) requires (!sad<T>);template <class T> int f1(T) requires (!sad<T>) && true;int i1 = f1(42); // ambiguous, !sad<T> atomic constraint expressions ([[temp.constr.atomic]](#temp.constr.atomic "13.5.2.3 Atomic constraints"))// are not formed from the same [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")template <class T> concept not_sad = !sad<T>;template <class T> int f2(T) requires not_sad<T>;template <class T> int f2(T) requires not_sad<T> && true;int i2 = f2(42); // OK, !sad<T> atomic constraint expressions both come from not_sadtemplate <class T> int f3(T) requires (!sad<typename T::type>);int i3 = f3(42); // error: associated constraints not satisfied due to substitution failuretemplate <class T> concept sad_nested_type = sad<typename T::type>;template <class T> int f4(T) requires (!sad_nested_type<T>);int i4 = f4(42); // OK, substitution failure contained within sad_nested_type
|
||||
|
||||
Here,requires (!sad<typename T::type>) requires
|
||||
that there is a nested type that is not sad,
|
||||
whereasrequires (!sad_nested_type<T>) requires
|
||||
that there is no sad nested type[.](#temp.constr.op-5.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
#### [13.5.2.3](#temp.constr.atomic) Atomic constraints [[temp.constr.atomic]](temp.constr.atomic)
|
||||
|
||||
[1](#temp.constr.atomic-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1738)
|
||||
|
||||
An [*atomic constraint*](#def:constraint,atomic "13.5.2.3 Atomic constraints [temp.constr.atomic]") is formed from
|
||||
an expression E and a mapping from the template parameters
|
||||
that appear within E to
|
||||
template arguments that are formed via substitution during constraint normalization
|
||||
in the declaration of a constrained entity (and, therefore, can involve the
|
||||
unsubstituted template parameters of the constrained entity),
|
||||
called the [*parameter mapping*](#def:parameter_mapping "13.5.2.3 Atomic constraints [temp.constr.atomic]") ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations"))[.](#temp.constr.atomic-1.sentence-1)
|
||||
|
||||
[*Note [1](#temp.constr.atomic-note-1)*:
|
||||
|
||||
Atomic constraints are formed by [constraint normalization](temp.constr.normal#def:constraint,normalization "13.5.4 Constraint normalization [temp.constr.normal]")[.](#temp.constr.atomic-1.sentence-2)
|
||||
|
||||
E is never a [logical and expression](expr.log.and "7.6.14 Logical AND operator [expr.log.and]") nor a [logical or expression](expr.log.or "7.6.15 Logical OR operator [expr.log.or]")[.](#temp.constr.atomic-1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#temp.constr.atomic-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1753)
|
||||
|
||||
Two atomic constraints, e1 and e2, are[*identical*](#def:atomic_constraint,identical "13.5.2.3 Atomic constraints [temp.constr.atomic]") if they are formed from the same appearance of the same[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") and if, given a hypothetical template A whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") consists of[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* corresponding and equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) to
|
||||
those mapped by the parameter mappings of the expression,
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are
|
||||
the targets of the parameter mapping of e1 is the same ([[temp.type]](temp.type "13.6 Type equivalence")) as
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are
|
||||
the targets of the parameter mapping of e2[.](#temp.constr.atomic-2.sentence-1)
|
||||
|
||||
[*Note [2](#temp.constr.atomic-note-2)*:
|
||||
|
||||
The comparison of parameter mappings of atomic constraints
|
||||
operates in a manner similar to that of declaration matching
|
||||
with alias template substitution ([[temp.alias]](temp.alias "13.7.8 Alias templates"))[.](#temp.constr.atomic-2.sentence-2)
|
||||
|
||||
[*Example [1](#temp.constr.atomic-example-1)*: template <unsigned N> constexpr bool Atomic = true;template <unsigned N> concept C = Atomic<N>;template <unsigned N> concept Add1 = C<N + 1>;template <unsigned N> concept AddOne = C<N + 1>;template <unsigned M> void f()requires Add1<2 * M>;template <unsigned M> int f()requires AddOne<2 * M> && true;
|
||||
|
||||
int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic<N>// with mapping similar to Nâ¦2 * M + 1template <unsigned N> struct WrapN;template <unsigned N> using Add1Ty = WrapN<N + 1>;template <unsigned N> using AddOneTy = WrapN<N + 1>;template <unsigned M> void g(Add1Ty<2 * M> *);template <unsigned M> void g(AddOneTy<2 * M> *);
|
||||
|
||||
void h() { g<0>(nullptr); // OK, there is only one g} â *end example*]
|
||||
|
||||
As specified in [[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"),
|
||||
if the validity or meaning of the program depends on
|
||||
whether two constructs are equivalent, and
|
||||
they are functionally equivalent but not equivalent,
|
||||
the program is ill-formed, no diagnostic required[.](#temp.constr.atomic-2.sentence-3)
|
||||
|
||||
[*Example [2](#temp.constr.atomic-example-2)*: template <unsigned N> void f2()requires Add1<2 * N>;template <unsigned N> int f2()requires Add1<N * 2> && true;void h2() { f2<0>(); // ill-formed, no diagnostic required:// requires determination of subsumption between atomic constraints that are// functionally equivalent but not equivalent} â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#temp.constr.atomic-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1819)
|
||||
|
||||
To determine if an atomic constraint is[*satisfied*](#def:constraint,satisfaction,atomic "13.5.2.3 Atomic constraints [temp.constr.atomic]"),
|
||||
the parameter mapping and template arguments are
|
||||
first substituted into its expression[.](#temp.constr.atomic-3.sentence-1)
|
||||
|
||||
If substitution results in an invalid type or expression
|
||||
in the immediate context of the atomic constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1 General")),
|
||||
the constraint is not satisfied[.](#temp.constr.atomic-3.sentence-2)
|
||||
|
||||
Otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2 Lvalue-to-rvalue conversion [conv.lval]") is performed if necessary,
|
||||
and E shall be a constant expression of type bool[.](#temp.constr.atomic-3.sentence-3)
|
||||
|
||||
The constraint is satisfied if and only if evaluation of E results in true[.](#temp.constr.atomic-3.sentence-4)
|
||||
|
||||
If, at different points in the program, the satisfaction result is different
|
||||
for identical atomic constraints and template arguments,
|
||||
the program is ill-formed, no diagnostic required[.](#temp.constr.atomic-3.sentence-5)
|
||||
|
||||
[*Example [3](#temp.constr.atomic-example-3)*: template<typename T> concept C =sizeof(T) == 4 && !true; // requires atomic constraints sizeof(T) == 4 and !truetemplate<typename T> struct S {constexpr operator bool() const { return true; }};
|
||||
|
||||
template<typename T> requires (S<T>{})void f(T); // #1void f(int); // #2void g() { f(0); // error: expression S<int>{} does not have type bool} // while checking satisfaction of deduced arguments of #1;// call is ill-formed even though #2 is a better match â *end example*]
|
||||
|
||||
#### [13.5.2.4](#temp.constr.concept) Concept-dependent constraints [[temp.constr.concept]](temp.constr.concept)
|
||||
|
||||
[1](#temp.constr.concept-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1857)
|
||||
|
||||
A [*concept-dependent constraint*](#def:constraint,concept-dependent "13.5.2.4 Concept-dependent constraints [temp.constr.concept]") CD is
|
||||
an atomic constraint whose expression is a concept-id CI whose[*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]") names a dependent concept named C[.](#temp.constr.concept-1.sentence-1)
|
||||
|
||||
[2](#temp.constr.concept-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1862)
|
||||
|
||||
To determine if CD is[*satisfied*](#def:constraint,satisfaction,concept-dependent "13.5.2.4 Concept-dependent constraints [temp.constr.concept]"),
|
||||
the parameter mapping and template arguments are first
|
||||
substituted into C[.](#temp.constr.concept-2.sentence-1)
|
||||
|
||||
If substitution results in an invalid concept-id in
|
||||
the immediate context of the constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1 General")),
|
||||
the constraint is not satisfied[.](#temp.constr.concept-2.sentence-2)
|
||||
|
||||
Otherwise, let CIâ² be
|
||||
the normal form ([[temp.constr.normal]](temp.constr.normal "13.5.4 Constraint normalization")) of the concept-id
|
||||
after substitution of C[.](#temp.constr.concept-2.sentence-3)
|
||||
|
||||
[*Note [1](#temp.constr.concept-note-1)*:
|
||||
|
||||
Normalization of CI might be ill-formed; no diagnostics is required[.](#temp.constr.concept-2.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#temp.constr.concept-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1877)
|
||||
|
||||
To form CIâ²â²,
|
||||
each appearance of C's template parameters in
|
||||
the parameter mappings of the atomic constraints
|
||||
(including concept-dependent constraints)
|
||||
in CIâ² is substituted with their respective arguments from
|
||||
the parameter mapping of CD and the arguments of CI[.](#temp.constr.concept-3.sentence-1)
|
||||
|
||||
[4](#temp.constr.concept-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1886)
|
||||
|
||||
CD is satisfied if CIâ²â² is satisfied[.](#temp.constr.concept-4.sentence-1)
|
||||
|
||||
[*Note [2](#temp.constr.concept-note-2)*:
|
||||
|
||||
Checking whether CIâ²â² is satisfied
|
||||
can lead to further normalization of concept-dependent constraints[.](#temp.constr.concept-4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#temp.constr.concept-example-1)*: template<typename>concept C = true;
|
||||
|
||||
template<typename T, template<typename> concept CC>concept D = CC<T>;
|
||||
|
||||
template<typename U, template<typename> concept CT, template<typename, template<typename> concept> concept CU>int f() requires CU<U, CT>;int i = f<int, C, D>();
|
||||
|
||||
In this example, the associated constraints of f consist of a concept-dependent constraint
|
||||
whose expression is the concept-id CU<U, CT> with the mappingUâ¦U,CTâ¦CT,CUâ¦CU[.](#temp.constr.concept-4.sentence-3)
|
||||
|
||||
The result of substituting D into this expression is D<U, CT>[.](#temp.constr.concept-4.sentence-4)
|
||||
|
||||
We consider the normal form of the resulting concept-id,
|
||||
which is CC<T> with the mappingTâ¦U,CCâ¦CT[.](#temp.constr.concept-4.sentence-5)
|
||||
|
||||
By recursion, C is substituted into CC<T>, and the result
|
||||
is normalized to the atomic constraint true, which is satisfied[.](#temp.constr.concept-4.sentence-6)
|
||||
|
||||
â *end example*]
|
||||
|
||||
#### [13.5.2.5](#temp.constr.fold) Fold expanded constraint [[temp.constr.fold]](temp.constr.fold)
|
||||
|
||||
[1](#temp.constr.fold-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1920)
|
||||
|
||||
A [*fold expanded constraint*](#def:constraint,fold_expanded "13.5.2.5 Fold expanded constraint [temp.constr.fold]") is formed from a constraint C and
|
||||
a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") which can either be && or ||[.](#temp.constr.fold-1.sentence-1)
|
||||
|
||||
A fold expanded constraint is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#temp.constr.fold-1.sentence-2)
|
||||
|
||||
Let N be the number of elements
|
||||
in the pack expansion parameters ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#temp.constr.fold-1.sentence-3)
|
||||
|
||||
[2](#temp.constr.fold-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1928)
|
||||
|
||||
A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") is && is satisfied if it is a valid pack expansion and
|
||||
if N=0 or if for each i where 0â¤i<N in increasing order,C is satisfied
|
||||
when replacing each pack expansion parameter
|
||||
with the corresponding ith element[.](#temp.constr.fold-2.sentence-1)
|
||||
|
||||
No substitution takes place for any i greater than
|
||||
the smallest i for which the constraint is not satisfied[.](#temp.constr.fold-2.sentence-2)
|
||||
|
||||
[3](#temp.constr.fold-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1938)
|
||||
|
||||
A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") is || is satisfied if it is a valid pack expansion,N>0, and if for i where 0â¤i<N in increasing order,
|
||||
there is a smallest i for which C is satisfied
|
||||
when replacing each pack expansion parameter
|
||||
with the corresponding ith element[.](#temp.constr.fold-3.sentence-1)
|
||||
|
||||
No substitution takes place for any i greater than
|
||||
the smallest i for which the constraint is satisfied[.](#temp.constr.fold-3.sentence-2)
|
||||
|
||||
[4](#temp.constr.fold-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1948)
|
||||
|
||||
[*Note [1](#temp.constr.fold-note-1)*:
|
||||
|
||||
If the pack expansion expands packs of different size,
|
||||
then it is invalid and the fold expanded constraint is not satisfied[.](#temp.constr.fold-4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#temp.constr.fold-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1954)
|
||||
|
||||
Two fold expanded constraints are [*compatible for subsumption*](#def:subsumption,compatible_for "13.5.2.5 Fold expanded constraint [temp.constr.fold]") if their respective constraints both contain
|
||||
an equivalent unexpanded pack ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"))[.](#temp.constr.fold-5.sentence-1)
|
||||
60
cppdraft/temp/constr/constr/general.md
Normal file
60
cppdraft/temp/constr/constr/general.md
Normal file
@@ -0,0 +1,60 @@
|
||||
[temp.constr.constr.general]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.5 Template constraints [[temp.constr]](temp.constr#constr.general)
|
||||
|
||||
### 13.5.2 Constraints [[temp.constr.constr]](temp.constr.constr#general)
|
||||
|
||||
#### 13.5.2.1 General [temp.constr.constr.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1610)
|
||||
|
||||
A [*constraint*](#def:constraint "13.5.2.1 General [temp.constr.constr.general]") is a sequence of logical operations and
|
||||
operands that specifies requirements on template arguments[.](#1.sentence-1)
|
||||
|
||||
The operands of a logical operation are constraints[.](#1.sentence-2)
|
||||
|
||||
There are five different kinds of constraints:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
conjunctions ([[temp.constr.op]](temp.constr.op "13.5.2.2 Logical operations")),
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
disjunctions ([[temp.constr.op]](temp.constr.op "13.5.2.2 Logical operations")),
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
atomic constraints ([[temp.constr.atomic]](temp.constr.atomic "13.5.2.3 Atomic constraints")),
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
concept-dependent constraints ([[temp.constr.concept]](temp.constr.concept "13.5.2.4 Concept-dependent constraints")), and
|
||||
|
||||
- [(1.5)](#1.5)
|
||||
|
||||
fold expanded constraints ([[temp.constr.fold]](temp.constr.fold "13.5.2.5 Fold expanded constraint"))[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1623)
|
||||
|
||||
In order for a constrained template to be instantiated ([[temp.spec]](temp.spec "13.9 Template instantiation and specialization")),
|
||||
its [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3 Constrained declarations [temp.constr.decl]") shall be satisfied as described in the following subclauses[.](#2.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Forming the name of a specialization of
|
||||
a class template,
|
||||
a variable template, or
|
||||
an alias template ([[temp.names]](temp.names "13.3 Names of template specializations"))
|
||||
requires the satisfaction of its constraints[.](#2.sentence-2)
|
||||
|
||||
[Overload resolution](over.match.viable "12.2.3 Viable functions [over.match.viable]") requires the satisfaction of constraints
|
||||
on functions and function templates[.](#2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
129
cppdraft/temp/constr/decl.md
Normal file
129
cppdraft/temp/constr/decl.md
Normal file
@@ -0,0 +1,129 @@
|
||||
[temp.constr.decl]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.5 Template constraints [[temp.constr]](temp.constr#decl)
|
||||
|
||||
### 13.5.3 Constrained declarations [temp.constr.decl]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1961)
|
||||
|
||||
A template declaration ([[temp.pre]](temp.pre "13.1 Preamble"))
|
||||
or templated function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))
|
||||
can be constrained by the use of a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")[.](#1.sentence-1)
|
||||
|
||||
This allows the specification of constraints for that declaration as
|
||||
an expression:
|
||||
|
||||
[constraint-expression:](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")
|
||||
[*logical-or-expression*](expr.log.or#nt:logical-or-expression "7.6.15 Logical OR operator [expr.log.or]")
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1972)
|
||||
|
||||
Constraints can also be associated with a declaration through the use of[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* in a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") or parameter-type-list[.](#2.sentence-1)
|
||||
|
||||
Each of these forms introduces additional [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* that are used to constrain the declaration[.](#2.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1979)
|
||||
|
||||
A declaration's [*associated constraints*](#def:associated_constraints "13.5.3 Constrained declarations [temp.constr.decl]") are defined as follows:
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
If there are no introduced [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s*,
|
||||
the declaration has no associated constraints[.](#3.1.sentence-1)
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
Otherwise, if there is a single introduced [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]"),
|
||||
the associated constraints are the [normal form](temp.constr.normal#def:normal_form,constraint "13.5.4 Constraint normalization [temp.constr.normal]") of that expression[.](#3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
Otherwise, the associated constraints are the normal form of a [logicaland expression](expr.log.and "7.6.14 Logical AND operator [expr.log.and]") whose operands are in the
|
||||
following order:
|
||||
* [(3.3.1)](#3.3.1)
|
||||
|
||||
the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
each [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")) in
|
||||
the declaration's [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]"),
|
||||
in order of appearance, and
|
||||
|
||||
* [(3.3.2)](#3.3.2)
|
||||
|
||||
the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") following
|
||||
a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble")), and
|
||||
|
||||
* [(3.3.3)](#3.3.3)
|
||||
|
||||
the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
each [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") in
|
||||
the parameter-type-list of a function declaration, and
|
||||
|
||||
* [(3.3.4)](#3.3.4)
|
||||
|
||||
the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[dcl.decl]](dcl.decl "9.3 Declarators")) of
|
||||
a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#3.3.sentence-1)
|
||||
|
||||
The formation of the associated constraints
|
||||
establishes the order in which constraints are instantiated when checking
|
||||
for satisfaction ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))[.](#3.sentence-2)
|
||||
|
||||
[*Example [1](#example-1)*: template<typename T> concept C = true;
|
||||
|
||||
template<C T> void f1(T);template<typename T> requires C<T> void f2(T);template<typename T> void f3(T) requires C<T>;
|
||||
|
||||
The functions f1, f2, and f3 have the associated
|
||||
constraint C<T>[.](#3.sentence-3)
|
||||
|
||||
template<typename T> concept C1 = true;template<typename T> concept C2 = sizeof(T) > 0;
|
||||
|
||||
template<C1 T> void f4(T) requires C2<T>;template<typename T> requires C1<T> && C2<T> void f5(T);
|
||||
|
||||
The associated constraints of f4 and f5 are C1<T> â§ C2<T>[.](#3.sentence-4)
|
||||
|
||||
template<C1 T> requires C2<T> void f6();template<C2 T> requires C1<T> void f7();
|
||||
|
||||
The associated constraints off6 are C1<T> â§ C2<T>,
|
||||
and those off7 are C2<T> â§ C1<T>[.](#3.sentence-5)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2051)
|
||||
|
||||
When determining whether a given introduced[*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") C1 of a declaration
|
||||
in an instantiated specialization of a templated class
|
||||
is equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) to the corresponding[*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") C2 of a declaration
|
||||
outside the class body,C1 is instantiated[.](#4.sentence-1)
|
||||
|
||||
If the instantiation results in an invalid expression,
|
||||
the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* are not equivalent[.](#4.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
This can happen when determining which member template is specialized
|
||||
by an explicit specialization declaration[.](#4.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#example-2)*: template <class T> concept C = true;template <class T> struct A {template <class U> U f(U) requires C<typename T::type>; // #1template <class U> U f(U) requires C<T>; // #2};
|
||||
|
||||
template <> template <class U> U A<int>::f(U u) requires C<int> { return u; } // OK, specializes #2
|
||||
|
||||
Substituting int for T in C<typename T::type> produces an invalid expression, so the specialization does not match #1[.](#4.sentence-4)
|
||||
|
||||
Substituting int for T in C<T> produces C<int>,
|
||||
which is equivalent to the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") for the specialization,
|
||||
so it does match #2[.](#4.sentence-5)
|
||||
|
||||
â *end example*]
|
||||
63
cppdraft/temp/constr/fold.md
Normal file
63
cppdraft/temp/constr/fold.md
Normal file
@@ -0,0 +1,63 @@
|
||||
[temp.constr.fold]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.5 Template constraints [[temp.constr]](temp.constr#fold)
|
||||
|
||||
### 13.5.2 Constraints [[temp.constr.constr]](temp.constr.constr#temp.constr.fold)
|
||||
|
||||
#### 13.5.2.5 Fold expanded constraint [temp.constr.fold]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1920)
|
||||
|
||||
A [*fold expanded constraint*](#def:constraint,fold_expanded "13.5.2.5 Fold expanded constraint [temp.constr.fold]") is formed from a constraint C and
|
||||
a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") which can either be && or ||[.](#1.sentence-1)
|
||||
|
||||
A fold expanded constraint is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#1.sentence-2)
|
||||
|
||||
Let N be the number of elements
|
||||
in the pack expansion parameters ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1928)
|
||||
|
||||
A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") is && is satisfied if it is a valid pack expansion and
|
||||
if N=0 or if for each i where 0â¤i<N in increasing order,C is satisfied
|
||||
when replacing each pack expansion parameter
|
||||
with the corresponding ith element[.](#2.sentence-1)
|
||||
|
||||
No substitution takes place for any i greater than
|
||||
the smallest i for which the constraint is not satisfied[.](#2.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1938)
|
||||
|
||||
A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") is || is satisfied if it is a valid pack expansion,N>0, and if for i where 0â¤i<N in increasing order,
|
||||
there is a smallest i for which C is satisfied
|
||||
when replacing each pack expansion parameter
|
||||
with the corresponding ith element[.](#3.sentence-1)
|
||||
|
||||
No substitution takes place for any i greater than
|
||||
the smallest i for which the constraint is satisfied[.](#3.sentence-2)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1948)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
If the pack expansion expands packs of different size,
|
||||
then it is invalid and the fold expanded constraint is not satisfied[.](#4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1954)
|
||||
|
||||
Two fold expanded constraints are [*compatible for subsumption*](#def:subsumption,compatible_for "13.5.2.5 Fold expanded constraint [temp.constr.fold]") if their respective constraints both contain
|
||||
an equivalent unexpanded pack ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"))[.](#5.sentence-1)
|
||||
24
cppdraft/temp/constr/general.md
Normal file
24
cppdraft/temp/constr/general.md
Normal file
@@ -0,0 +1,24 @@
|
||||
[temp.constr.general]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.5 Template constraints [[temp.constr]](temp.constr#general)
|
||||
|
||||
### 13.5.1 General [temp.constr.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1595)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Subclause [[temp.constr]](temp.constr "13.5 Template constraints") defines the meaning of constraints on template arguments[.](#1.sentence-1)
|
||||
|
||||
The abstract syntax and satisfaction rules are defined
|
||||
in [[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints")[.](#1.sentence-2)
|
||||
|
||||
Constraints are associated with declarations in [[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations")[.](#1.sentence-3)
|
||||
|
||||
Declarations are partially ordered by their associated constraints ([[temp.constr.order]](temp.constr.order "13.5.5 Partial ordering by constraints"))[.](#1.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
190
cppdraft/temp/constr/normal.md
Normal file
190
cppdraft/temp/constr/normal.md
Normal file
@@ -0,0 +1,190 @@
|
||||
[temp.constr.normal]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.5 Template constraints [[temp.constr]](temp.constr#normal)
|
||||
|
||||
### 13.5.4 Constraint normalization [temp.constr.normal]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2085)
|
||||
|
||||
The [*normal form*](#def:normal_form,constraint "13.5.4 Constraint normalization [temp.constr.normal]") of an [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") E is
|
||||
a [constraint](temp.constr.constr#def:constraint "13.5.2 Constraints [temp.constr.constr]") that is defined as follows:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
The normal form of an expression ( E ) is
|
||||
the normal form of E[.](#1.1.sentence-1)
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
The normal form of an expression E1 || E2 is
|
||||
the [disjunction](temp.constr.op#def:disjunction "13.5.2.2 Logical operations [temp.constr.op]") of
|
||||
the normal forms of E1 and E2[.](#1.2.sentence-1)
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
The normal form of an expression E1 && E2 is the conjunction of
|
||||
the normal forms of E1 and E2[.](#1.3.sentence-1)
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
For a concept-id C<A1, A2, …, An> termed CI:
|
||||
* [(1.4.1)](#1.4.1)
|
||||
|
||||
If C names a dependent concept,
|
||||
the normal form of CI is a concept-dependent constraint
|
||||
whose concept-id is CI and
|
||||
whose parameter mapping is the identity mapping[.](#1.4.1.sentence-1)
|
||||
|
||||
* [(1.4.2)](#1.4.2)
|
||||
|
||||
Otherwise, to form CE,
|
||||
any non-dependent concept template argument Ai is substituted into the [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") of C[.](#1.4.2.sentence-1)
|
||||
If any such substitution results in an invalid concept-id,
|
||||
the program is ill-formed; no diagnostic is required[.](#1.4.2.sentence-2)
|
||||
The normal form of CI is the result of substituting,
|
||||
in the normal form N of CE,
|
||||
appearances of C's template parameters
|
||||
in the parameter mappings of the atomic constraints in N with their respective arguments from C[.](#1.4.2.sentence-3)
|
||||
If any such substitution results in an invalid type or expression,
|
||||
the program is ill-formed; no diagnostic is required[.](#1.4.2.sentence-4)
|
||||
|
||||
[*Example [1](#example-1)*: template<typename T> concept A = T::value || true;template<typename U> concept B = A<U*>;template<typename V> concept C = B<V&>;
|
||||
Normalization of B's [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") is valid and results inT::value (with the mapping Tâ¦U*) ⨠true (with an empty mapping),
|
||||
despite the expression T::value being ill-formed
|
||||
for a pointer type T[.](#1.4.sentence-2)
|
||||
Normalization of C's [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") results in the program being ill-formed,
|
||||
because it would form the invalid type V&* in the parameter mapping[.](#1.4.sentence-3)
|
||||
â *end example*]
|
||||
|
||||
- [(1.5)](#1.5)
|
||||
|
||||
For a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") Op ([[expr.prim.fold]](expr.prim.fold "7.5.7 Fold expressions"))
|
||||
that is either && or ||:
|
||||
* [(1.5.1)](#1.5.1)
|
||||
|
||||
The normal form of an expression ( ... Op E ) is the normal form of ( E Op ... )[.](#1.5.1.sentence-1)
|
||||
|
||||
* [(1.5.2)](#1.5.2)
|
||||
|
||||
The normal form of an expression ( E1 Op ... Op E2 ) is the normal form of
|
||||
+
|
||||
[(1.5.2.1)](#1.5.2.1)
|
||||
( E1 Op ... ) Op E2 if E1 contains an unexpanded pack, or
|
||||
|
||||
+
|
||||
[(1.5.2.2)](#1.5.2.2)
|
||||
E1 Op ( E2 Op ... ) otherwise[.](#1.5.2.sentence-1)
|
||||
|
||||
* [(1.5.3)](#1.5.3)
|
||||
|
||||
The normal form of an expression F of the form ( E Op ... ) is as follows:
|
||||
If E contains an unexpanded concept template parameter pack,
|
||||
it shall not contain an unexpanded template parameter pack of another kind[.](#1.5.3.sentence-2)
|
||||
Let Eâ² be the normal form of E[.](#1.5.3.sentence-3)
|
||||
|
||||
+
|
||||
[(1.5.3.1)](#1.5.3.1)
|
||||
If E contains
|
||||
an unexpanded concept template parameter pack Pk that
|
||||
has corresponding template arguments in
|
||||
the parameter mapping of any atomic constraint
|
||||
(including concept-dependent constraints) of Eâ²,
|
||||
the number of arguments specified for all such Pk shall be the same number N[.](#1.5.3.1.sentence-1)
|
||||
The normal form of F is the normal form of E0 Op Op ENâ1 after substituting in Ei the respective ith concept argument of each Pk[.](#1.5.3.1.sentence-2)
|
||||
If any such substitution results in an invalid type or expression,
|
||||
the program is ill-formed; no diagnostic is required[.](#1.5.3.1.sentence-3)
|
||||
|
||||
+
|
||||
[(1.5.3.2)](#1.5.3.2)
|
||||
Otherwise,
|
||||
the normal form of F is
|
||||
a fold expanded constraint ([[temp.constr.fold]](temp.constr.fold "13.5.2.5 Fold expanded constraint")) whose
|
||||
constraint is Eâ² and whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]") is Op[.](#1.5.3.2.sentence-1)
|
||||
|
||||
- [(1.6)](#1.6)
|
||||
|
||||
The normal form of any other expression E is
|
||||
the atomic constraint
|
||||
whose expression is E and
|
||||
whose parameter mapping is the identity mapping[.](#1.6.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2201)
|
||||
|
||||
The process of obtaining the normal form of a[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") is called[*normalization*](#def:constraint,normalization "13.5.4 Constraint normalization [temp.constr.normal]")[.](#2.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Normalization of [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* is performed
|
||||
when determining the associated constraints ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))
|
||||
of a declaration
|
||||
and
|
||||
when evaluating the value of an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") that names a concept specialization ([[expr.prim.id]](expr.prim.id "7.5.5 Names"))[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2217)
|
||||
|
||||
[*Example [2](#example-2)*: template<typename T> concept C1 = sizeof(T) == 1;template<typename T> concept C2 = C1<T> && 1 == 2;template<typename T> concept C3 = requires { typename T::type; };template<typename T> concept C4 = requires (T x) { ++x; };
|
||||
|
||||
template<C2 U> void f1(U); // #1template<C3 U> void f2(U); // #2template<C4 U> void f3(U); // #3
|
||||
|
||||
The associated constraints of #1 aresizeof(T) == 1 (with mapping Tâ¦U) â§ 1 == 2[.](#3.sentence-1)
|
||||
|
||||
|
||||
|
||||
|
||||
The associated constraints of #2 arerequires { typename T::type; } (with mapping Tâ¦U)[.](#3.sentence-2)
|
||||
|
||||
|
||||
|
||||
|
||||
The associated constraints of #3 arerequires (T x) { ++x; } (with mapping Tâ¦U)[.](#3.sentence-3)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[*Example [3](#example-3)*: template<typename T>concept C = true;template<typename T, template<typename> concept CT>concept CC = CT<T>;
|
||||
|
||||
template<typename U, template<typename, template<typename> concept> concept CT>void f() requires CT<U*, C>;template<typename U>void g() requires CC<U*, C>;
|
||||
|
||||
The normal form of the associated constraints of f is
|
||||
the concept-dependent constraint CT<T, C>[.](#3.sentence-4)
|
||||
|
||||
|
||||
|
||||
|
||||
The normal form of the associated constraints of g is
|
||||
the atomic constraint true[.](#3.sentence-5)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[*Example [4](#example-4)*: template<typename T>concept A = true;template<typename T>concept B = A<T> && true; // B subsumes Atemplate<typename T>concept C = true;template<typename T>concept D = C<T> && true; // D subsumes Ctemplate<typename T, template<typename> concept... CTs>concept all_of = (CTs<T> && ...);
|
||||
|
||||
template<typename T> requires all_of<T, A, C>constexpr int f(T) { return 1; } // #1template<typename T> requires all_of<T, B, D>constexpr int f(T) { return 2; } // #2static_assert(f(1) == 2); // ok
|
||||
|
||||
The normal form of all_of<T, A, C> is
|
||||
the conjunction of the normal forms of A<T> and C<T>[.](#3.sentence-6)
|
||||
|
||||
|
||||
|
||||
|
||||
Similarly, the normal form of all_of<T, B, D> is
|
||||
the conjunction of the normal forms of B<T> and D<T>[.](#3.sentence-7)
|
||||
|
||||
|
||||
|
||||
|
||||
#2 therefore is more constrained than #1[.](#3.sentence-8)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[*Example [5](#example-5)*: template<typename T, template<typename> concept>struct wrapper {};
|
||||
|
||||
template<typename... T, template<typename> concept... CTs>int f(wrapper<T, CTs>...) requires (CTs<T> && ...); // error: fold expression contains// different kinds of template parameters â *end example*]
|
||||
105
cppdraft/temp/constr/op.md
Normal file
105
cppdraft/temp/constr/op.md
Normal file
@@ -0,0 +1,105 @@
|
||||
[temp.constr.op]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.5 Template constraints [[temp.constr]](temp.constr#op)
|
||||
|
||||
### 13.5.2 Constraints [[temp.constr.constr]](temp.constr.constr#temp.constr.op)
|
||||
|
||||
#### 13.5.2.2 Logical operations [temp.constr.op]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1640)
|
||||
|
||||
There are two binary logical operations on constraints: conjunction
|
||||
and disjunction[.](#1.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
These logical operations have no corresponding C++ syntax[.](#1.sentence-2)
|
||||
|
||||
For the purpose of exposition, conjunction is spelled
|
||||
using the symbol â§ and disjunction is spelled using the
|
||||
symbol ⨠[.](#1.sentence-3)
|
||||
|
||||
The operands of these operations are called the left
|
||||
and right operands[.](#1.sentence-4)
|
||||
|
||||
In the constraint A â§ B,A is the left operand, and B is the right operand[.](#1.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1653)
|
||||
|
||||
A [*conjunction*](#def:conjunction "13.5.2.2 Logical operations [temp.constr.op]") is a constraint taking two
|
||||
operands[.](#2.sentence-1)
|
||||
|
||||
To determine if a conjunction is[*satisfied*](#def:constraint,satisfaction,conjunction "13.5.2.2 Logical operations [temp.constr.op]"),
|
||||
the satisfaction of
|
||||
the first operand is checked[.](#2.sentence-2)
|
||||
|
||||
If that is not satisfied, the conjunction is not satisfied[.](#2.sentence-3)
|
||||
|
||||
Otherwise, the conjunction is satisfied if and only if the second
|
||||
operand is satisfied[.](#2.sentence-4)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1664)
|
||||
|
||||
A [*disjunction*](#def:disjunction "13.5.2.2 Logical operations [temp.constr.op]") is a constraint taking two
|
||||
operands[.](#3.sentence-1)
|
||||
|
||||
To determine if a disjunction is[*satisfied*](#def:constraint,satisfaction,disjunction "13.5.2.2 Logical operations [temp.constr.op]"),
|
||||
the satisfaction of
|
||||
the first operand is checked[.](#3.sentence-2)
|
||||
|
||||
If that is satisfied, the disjunction is satisfied[.](#3.sentence-3)
|
||||
|
||||
Otherwise, the disjunction is satisfied if and only if the second
|
||||
operand is satisfied[.](#3.sentence-4)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1676)
|
||||
|
||||
[*Example [1](#example-1)*: template<typename T>constexpr bool get_value() { return T::value; }template<typename T>requires (sizeof(T) > 1) && (get_value<T>())void f(T); // has associated constraint sizeof(T) > 1 â§ get_value<T>()void f(int);
|
||||
|
||||
f('a'); // OK, calls f(int)
|
||||
|
||||
In the satisfaction of the [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3 Constrained declarations [temp.constr.decl]") of f, the constraint sizeof(char) > 1 is not satisfied;
|
||||
the second operand is not checked for satisfaction[.](#4.sentence-1)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1695)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
A logical negation expression ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary operators")) is an atomic constraint;
|
||||
the negation operator is not treated as a logical operation on constraints[.](#5.sentence-1)
|
||||
|
||||
As a result, distinct negation [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* that are equivalent under [[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading") do not subsume one another under [[temp.constr.order]](temp.constr.order "13.5.5 Partial ordering by constraints")[.](#5.sentence-2)
|
||||
|
||||
Furthermore, if substitution to determine
|
||||
whether an atomic constraint is satisfied ([[temp.constr.atomic]](temp.constr.atomic "13.5.2.3 Atomic constraints"))
|
||||
encounters a substitution failure, the constraint is not satisfied,
|
||||
regardless of the presence of a negation operator[.](#5.sentence-3)
|
||||
|
||||
[*Example [2](#example-2)*: template <class T> concept sad = false;
|
||||
|
||||
template <class T> int f1(T) requires (!sad<T>);template <class T> int f1(T) requires (!sad<T>) && true;int i1 = f1(42); // ambiguous, !sad<T> atomic constraint expressions ([[temp.constr.atomic]](temp.constr.atomic "13.5.2.3 Atomic constraints"))// are not formed from the same [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")template <class T> concept not_sad = !sad<T>;template <class T> int f2(T) requires not_sad<T>;template <class T> int f2(T) requires not_sad<T> && true;int i2 = f2(42); // OK, !sad<T> atomic constraint expressions both come from not_sadtemplate <class T> int f3(T) requires (!sad<typename T::type>);int i3 = f3(42); // error: associated constraints not satisfied due to substitution failuretemplate <class T> concept sad_nested_type = sad<typename T::type>;template <class T> int f4(T) requires (!sad_nested_type<T>);int i4 = f4(42); // OK, substitution failure contained within sad_nested_type
|
||||
|
||||
Here,requires (!sad<typename T::type>) requires
|
||||
that there is a nested type that is not sad,
|
||||
whereasrequires (!sad_nested_type<T>) requires
|
||||
that there is no sad nested type[.](#5.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
|
||||
â *end note*]
|
||||
157
cppdraft/temp/constr/order.md
Normal file
157
cppdraft/temp/constr/order.md
Normal file
@@ -0,0 +1,157 @@
|
||||
[temp.constr.order]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.5 Template constraints [[temp.constr]](temp.constr#order)
|
||||
|
||||
### 13.5.5 Partial ordering by constraints [temp.constr.order]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2299)
|
||||
|
||||
A constraint P [*subsumes*](#def:constraint,subsumption "13.5.5 Partial ordering by constraints [temp.constr.order]") a constraint Q if and only if,
|
||||
for every disjunctive clause Pi in the disjunctive normal form[110](#footnote-110 "A constraint is in disjunctive normal form when it is a disjunction of clauses where each clause is a conjunction of fold expanded or atomic constraints. For atomic constraints A, B, and C, the disjunctive normal form of the constraint A ⧠(B ⨠C) is (A ⧠B) ⨠(A ⧠C). Its disjunctive clauses are (A ⧠B) and (A ⧠C).") of P, Pi subsumes every conjunctive clause Qj in the conjunctive normal form[111](#footnote-111 "A constraint is in conjunctive normal form when it is a conjunction of clauses where each clause is a disjunction of fold expanded or atomic constraints. For atomic constraints A, B, and C, the constraint A ⧠(B ⨠C) is in conjunctive normal form. Its conjunctive clauses are A and (B ⨠C).") of Q, where
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
a disjunctive clause Pi subsumes a conjunctive clause Qj if and only
|
||||
if there exists an atomic constraint Pia in Pi for which there exists
|
||||
an atomic constraint Qjb in Qj such that Pia subsumes Qjb,
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
an atomic constraint A subsumes another atomic constraintB if and only if A and B are identical using the
|
||||
rules described in [[temp.constr.atomic]](temp.constr.atomic "13.5.2.3 Atomic constraints"), and
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
a fold expanded constraint A subsumes
|
||||
another fold expanded constraint B if they are compatible for subsumption,
|
||||
have the same [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold expressions [expr.prim.fold]"), and
|
||||
the constraint of A subsumes that of B[.](#1.sentence-1)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
Let A and B be [atomic constraints](temp.constr.atomic#def:constraint,atomic "13.5.2.3 Atomic constraints [temp.constr.atomic]")[.](#1.sentence-2)
|
||||
|
||||
The constraint A â§ B subsumes A, but A does not subsume A â§ B[.](#1.sentence-3)
|
||||
|
||||
The constraint A subsumes A ⨠B, but A ⨠B does not subsume A[.](#1.sentence-4)
|
||||
|
||||
Also note that every constraint subsumes itself[.](#1.sentence-5)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2354)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The subsumption relation defines a partial ordering on constraints[.](#2.sentence-1)
|
||||
|
||||
This partial ordering is used to determine
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
the best viable candidate of non-template functions ([[over.match.best]](over.match.best "12.2.4 Best viable function")),
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
the address of a non-template function ([[over.over]](over.over "12.3 Address of an overload set")),
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
the matching of template template arguments ([[temp.arg.template]](temp.arg.template "13.4.4 Template template arguments")),
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
the partial ordering of class template specializations ([[temp.spec.partial.order]](temp.spec.partial.order "13.7.6.3 Partial ordering of partial specializations")), and
|
||||
|
||||
- [(2.5)](#2.5)
|
||||
|
||||
the partial ordering of function templates ([[temp.func.order]](temp.func.order "13.7.7.3 Partial ordering of function templates"))[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2367)
|
||||
|
||||
The associated constraints C of a declaration Dare [*eligible for subsumption*](#def:eligible,for_subsumption "13.5.5 Partial ordering by constraints [temp.constr.order]") unless C contains a concept-dependent constraint[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2378)
|
||||
|
||||
A declaration D1 is[*at least as constrained*](#def:at_least_as_constrained "13.5.5 Partial ordering by constraints [temp.constr.order]") as
|
||||
a declaration D2 if
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
D1 and D2 are both constrained declarations andD1's associated constraints
|
||||
are eligible for subsumption and subsume those of D2; or
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
D2 has no associated constraints[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2390)
|
||||
|
||||
A declaration D1 is [*more constrained*](#def:more_constrained "13.5.5 Partial ordering by constraints [temp.constr.order]") than another declaration D2 when D1 is at least as
|
||||
constrained as D2, and D2 is not at least as
|
||||
constrained as D1[.](#5.sentence-1)
|
||||
|
||||
[*Example [2](#example-2)*: template<typename T> concept C1 = requires(T t) { --t; };template<typename T> concept C2 = C1<T> && requires(T t) { *t; };
|
||||
|
||||
template<C1 T> void f(T); // #1template<C2 T> void f(T); // #2template<typename T> void g(T); // #3template<C1 T> void g(T); // #4 f(0); // selects #1 f((int*)0); // selects #2 g(true); // selects #3 because C1<bool> is not satisfied g(0); // selects #4 â *end example*]
|
||||
|
||||
[*Example [3](#example-3)*: template<template<typename T> concept CT, typename T>struct S {};template<typename T>concept A = true;
|
||||
|
||||
template<template<typename T> concept X, typename T>int f(S<X, T>) requires A<T> { return 42; } // #1template<template<typename T> concept X, typename T>int f(S<X, T>) requires X<T> { return 43; } // #2 f(S<A, int>{}); // ok, select #1 because #2 is not eligible for subsumption â *end example*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2427)
|
||||
|
||||
A non-template function F1 is [*more partial-ordering-constrained*](#def:more_partial-ordering-constrained "13.5.5 Partial ordering by constraints [temp.constr.order]") than a non-template function F2 if
|
||||
|
||||
- [(6.1)](#6.1)
|
||||
|
||||
they have the same non-object-parameter-type-lists ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")), and
|
||||
|
||||
- [(6.2)](#6.2)
|
||||
|
||||
if they are member functions, both are direct members of the same class, and
|
||||
|
||||
- [(6.3)](#6.3)
|
||||
|
||||
if both are non-static member functions,
|
||||
they have the same types for their object parameters, and
|
||||
|
||||
- [(6.4)](#6.4)
|
||||
|
||||
the declaration of F1 is more constrained than
|
||||
the declaration of F2[.](#6.sentence-1)
|
||||
|
||||
[110)](#footnote-110)[110)](#footnoteref-110)
|
||||
|
||||
A constraint is in disjunctive normal form when it is a disjunction of
|
||||
clauses where each clause is a conjunction of fold expanded or atomic constraints[.](#footnote-110.sentence-1)
|
||||
|
||||
For atomic constraints A, B, and C, the disjunctive normal form
|
||||
of the constraintA ⧠(B ⨠C) is(A ⧠B) ⨠(A ⧠C)[.](#footnote-110.sentence-2)
|
||||
|
||||
Its disjunctive clauses are (A â§ B) and (A â§ C)[.](#footnote-110.sentence-3)
|
||||
|
||||
[111)](#footnote-111)[111)](#footnoteref-111)
|
||||
|
||||
A constraint is in conjunctive normal form when it is a conjunction
|
||||
of clauses where each clause is a disjunction of fold expanded or atomic constraints[.](#footnote-111.sentence-1)
|
||||
|
||||
For atomic constraints A, B, and C, the constraintA ⧠(B ⨠C) is in conjunctive normal form[.](#footnote-111.sentence-2)
|
||||
|
||||
Its conjunctive clauses are A and (B ⨠C)[.](#footnote-111.sentence-3)
|
||||
Reference in New Issue
Block a user