- tmp/tmpl7njrojk/{from.md → to.md} +234 -15
tmp/tmpl7njrojk/{from.md → to.md}
RENAMED
|
@@ -12,16 +12,18 @@ by their associated constraints [[temp.constr.order]]. — *end note*]
|
|
| 12 |
|
| 13 |
#### General <a id="temp.constr.constr.general">[[temp.constr.constr.general]]</a>
|
| 14 |
|
| 15 |
A *constraint* is a sequence of logical operations and operands that
|
| 16 |
specifies requirements on template arguments. The operands of a logical
|
| 17 |
-
operation are constraints. There are
|
| 18 |
constraints:
|
| 19 |
|
| 20 |
- conjunctions [[temp.constr.op]],
|
| 21 |
-
- disjunctions [[temp.constr.op]],
|
| 22 |
-
- atomic constraints [[temp.constr.atomic]]
|
|
|
|
|
|
|
| 23 |
|
| 24 |
In order for a constrained template to be instantiated [[temp.spec]],
|
| 25 |
its associated constraints [[temp.constr.decl]] shall be satisfied as
|
| 26 |
described in the following subclauses.
|
| 27 |
|
|
@@ -200,11 +202,12 @@ void h2() {
|
|
| 200 |
|
| 201 |
— *end note*]
|
| 202 |
|
| 203 |
To determine if an atomic constraint is *satisfied*, the parameter
|
| 204 |
mapping and template arguments are first substituted into its
|
| 205 |
-
expression. If substitution results in an invalid type or expression
|
|
|
|
| 206 |
the constraint is not satisfied. Otherwise, the lvalue-to-rvalue
|
| 207 |
conversion [[conv.lval]] is performed if necessary, and `E` shall be a
|
| 208 |
constant expression of type `bool`. The constraint is satisfied if and
|
| 209 |
only if evaluation of `E` results in `true`. If, at different points in
|
| 210 |
the program, the satisfaction result is different for identical atomic
|
|
@@ -231,10 +234,93 @@ void g() {
|
|
| 231 |
// call is ill-formed even though #2 is a better match
|
| 232 |
```
|
| 233 |
|
| 234 |
— *end example*]
|
| 235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
### Constrained declarations <a id="temp.constr.decl">[[temp.constr.decl]]</a>
|
| 237 |
|
| 238 |
A template declaration [[temp.pre]] or templated function declaration
|
| 239 |
[[dcl.fct]] can be constrained by the use of a *requires-clause*. This
|
| 240 |
allows the specification of constraints for that declaration as an
|
|
@@ -345,16 +431,24 @@ The *normal form* of an *expression* `E` is a constraint
|
|
| 345 |
- The normal form of an expression `( E )` is the normal form of `E`.
|
| 346 |
- The normal form of an expression `E1 || E2` is the disjunction
|
| 347 |
[[temp.constr.op]] of the normal forms of `E1` and `E2`.
|
| 348 |
- The normal form of an expression `E1 && E2` is the conjunction of the
|
| 349 |
normal forms of `E1` and `E2`.
|
| 350 |
-
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 356 |
\[*Example 1*:
|
| 357 |
``` cpp
|
| 358 |
template<typename T> concept A = T::value || true;
|
| 359 |
template<typename U> concept B = A<U*>;
|
| 360 |
template<typename V> concept C = B<V&>;
|
|
@@ -365,10 +459,35 @@ The *normal form* of an *expression* `E` is a constraint
|
|
| 365 |
mapping), despite the expression `T::value` being ill-formed for a
|
| 366 |
pointer type `T`. Normalization of `C`'s *constraint-expression*
|
| 367 |
results in the program being ill-formed, because it would form the
|
| 368 |
invalid type `V&*` in the parameter mapping.
|
| 369 |
— *end example*]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 370 |
- The normal form of any other expression `E` is the atomic constraint
|
| 371 |
whose expression is `E` and whose parameter mapping is the identity
|
| 372 |
mapping.
|
| 373 |
|
| 374 |
The process of obtaining the normal form of a *constraint-expression* is
|
|
@@ -399,27 +518,95 @@ The associated constraints of \#2 are `requires { typename T::type; }`
|
|
| 399 |
The associated constraints of \#3 are `requires (T x) { ++x; }` (with
|
| 400 |
mapping `T` ↦ `U`).
|
| 401 |
|
| 402 |
— *end example*]
|
| 403 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 404 |
### Partial ordering by constraints <a id="temp.constr.order">[[temp.constr.order]]</a>
|
| 405 |
|
| 406 |
A constraint P *subsumes* a constraint Q if and only if, for every
|
| 407 |
-
disjunctive clause Pᵢ in the disjunctive normal form[^
|
| 408 |
|
| 409 |
of P, Pᵢ subsumes every conjunctive clause Qⱼ in the conjunctive normal
|
| 410 |
-
form[^
|
| 411 |
|
| 412 |
of Q, where
|
| 413 |
|
| 414 |
- a disjunctive clause Pᵢ subsumes a conjunctive clause Qⱼ if and only
|
| 415 |
if there exists an atomic constraint Pᵢₐ in Pᵢ for which there exists
|
| 416 |
an atomic constraint $Q_{jb}$ in Qⱼ such that Pᵢₐ subsumes $Q_{jb}$,
|
| 417 |
-
and
|
| 418 |
- an atomic constraint A subsumes another atomic constraint B if and
|
| 419 |
only if A and B are identical using the rules described in
|
| 420 |
-
[[temp.constr.atomic]]
|
|
|
|
|
|
|
|
|
|
| 421 |
|
| 422 |
[*Example 1*: Let A and B be atomic constraints [[temp.constr.atomic]].
|
| 423 |
The constraint A ∧ B subsumes A, but A does not subsume A ∧ B. The
|
| 424 |
constraint A subsumes A ∨ B, but A ∨ B does not subsume A. Also note
|
| 425 |
that every constraint subsumes itself. — *end example*]
|
|
@@ -437,14 +624,17 @@ partial ordering is used to determine
|
|
| 437 |
[[temp.spec.partial.order]], and
|
| 438 |
- the partial ordering of function templates [[temp.func.order]].
|
| 439 |
|
| 440 |
— *end note*]
|
| 441 |
|
|
|
|
|
|
|
|
|
|
| 442 |
A declaration `D1` is *at least as constrained* as a declaration `D2` if
|
| 443 |
|
| 444 |
- `D1` and `D2` are both constrained declarations and `D1`’s associated
|
| 445 |
-
constraints subsume those of `D2`; or
|
| 446 |
- `D2` has no associated constraints.
|
| 447 |
|
| 448 |
A declaration `D1` is *more constrained* than another declaration `D2`
|
| 449 |
when `D1` is at least as constrained as `D2`, and `D2` is not at least
|
| 450 |
as constrained as `D1`.
|
|
@@ -466,5 +656,34 @@ g(true); // selects #3 because C1<bool> is not satisfied
|
|
| 466 |
g(0); // selects #4
|
| 467 |
```
|
| 468 |
|
| 469 |
— *end example*]
|
| 470 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
#### General <a id="temp.constr.constr.general">[[temp.constr.constr.general]]</a>
|
| 14 |
|
| 15 |
A *constraint* is a sequence of logical operations and operands that
|
| 16 |
specifies requirements on template arguments. The operands of a logical
|
| 17 |
+
operation are constraints. There are five different kinds of
|
| 18 |
constraints:
|
| 19 |
|
| 20 |
- conjunctions [[temp.constr.op]],
|
| 21 |
+
- disjunctions [[temp.constr.op]],
|
| 22 |
+
- atomic constraints [[temp.constr.atomic]],
|
| 23 |
+
- concept-dependent constraints [[temp.constr.concept]], and
|
| 24 |
+
- fold expanded constraints [[temp.constr.fold]].
|
| 25 |
|
| 26 |
In order for a constrained template to be instantiated [[temp.spec]],
|
| 27 |
its associated constraints [[temp.constr.decl]] shall be satisfied as
|
| 28 |
described in the following subclauses.
|
| 29 |
|
|
|
|
| 202 |
|
| 203 |
— *end note*]
|
| 204 |
|
| 205 |
To determine if an atomic constraint is *satisfied*, the parameter
|
| 206 |
mapping and template arguments are first substituted into its
|
| 207 |
+
expression. If substitution results in an invalid type or expression in
|
| 208 |
+
the immediate context of the atomic constraint [[temp.deduct.general]],
|
| 209 |
the constraint is not satisfied. Otherwise, the lvalue-to-rvalue
|
| 210 |
conversion [[conv.lval]] is performed if necessary, and `E` shall be a
|
| 211 |
constant expression of type `bool`. The constraint is satisfied if and
|
| 212 |
only if evaluation of `E` results in `true`. If, at different points in
|
| 213 |
the program, the satisfaction result is different for identical atomic
|
|
|
|
| 234 |
// call is ill-formed even though #2 is a better match
|
| 235 |
```
|
| 236 |
|
| 237 |
— *end example*]
|
| 238 |
|
| 239 |
+
#### Concept-dependent constraints <a id="temp.constr.concept">[[temp.constr.concept]]</a>
|
| 240 |
+
|
| 241 |
+
A *concept-dependent constraint* `CD` is an atomic constraint whose
|
| 242 |
+
expression is a concept-id `CI` whose *concept-name* names a dependent
|
| 243 |
+
concept named `C`.
|
| 244 |
+
|
| 245 |
+
To determine if `CD` is *satisfied*, the parameter mapping and template
|
| 246 |
+
arguments are first substituted into `C`. If substitution results in an
|
| 247 |
+
invalid concept-id in the immediate context of the constraint
|
| 248 |
+
[[temp.deduct.general]], the constraint is not satisfied. Otherwise, let
|
| 249 |
+
`CI'` be the normal form [[temp.constr.normal]] of the concept-id after
|
| 250 |
+
substitution of `C`.
|
| 251 |
+
|
| 252 |
+
[*Note 1*: Normalization of `CI` might be ill-formed; no diagnostic is
|
| 253 |
+
required. — *end note*]
|
| 254 |
+
|
| 255 |
+
To form `CI''`, each appearance of `C`'s template parameters in the
|
| 256 |
+
parameter mappings of the atomic constraints (including
|
| 257 |
+
concept-dependent constraints) in `CI'` is substituted with their
|
| 258 |
+
respective arguments from the parameter mapping of `CD` and the
|
| 259 |
+
arguments of `CI`.
|
| 260 |
+
|
| 261 |
+
`CD` is satisfied if `CI''` is satisfied.
|
| 262 |
+
|
| 263 |
+
[*Note 2*: Checking whether `CI''` is satisfied can lead to further
|
| 264 |
+
normalization of concept-dependent constraints. — *end note*]
|
| 265 |
+
|
| 266 |
+
[*Example 1*:
|
| 267 |
+
|
| 268 |
+
``` cpp
|
| 269 |
+
template<typename>
|
| 270 |
+
concept C = true;
|
| 271 |
+
|
| 272 |
+
template<typename T, template<typename> concept CC>
|
| 273 |
+
concept D = CC<T>;
|
| 274 |
+
|
| 275 |
+
template<typename U,
|
| 276 |
+
template<typename> concept CT,
|
| 277 |
+
template<typename, template<typename> concept> concept CU>
|
| 278 |
+
int f() requires CU<U, CT>;
|
| 279 |
+
int i = f<int, C, D>();
|
| 280 |
+
```
|
| 281 |
+
|
| 282 |
+
In this example, the associated constraints of `f` consist of a
|
| 283 |
+
concept-dependent constraint whose expression is the concept-id
|
| 284 |
+
`CU<U, CT>` with the mapping `U` ↦ `U`, `CT` ↦ `CT`, `CU` ↦ `CU`. The
|
| 285 |
+
result of substituting `D` into this expression is `D<U, CT>`. We
|
| 286 |
+
consider the normal form of the resulting concept-id, which is `CC<T>`
|
| 287 |
+
with the mapping `T` ↦ `U`, `CC` ↦ `CT`. By recursion, `C` is
|
| 288 |
+
substituted into `CC<T>`, and the result is normalized to the atomic
|
| 289 |
+
constraint `true`, which is satisfied.
|
| 290 |
+
|
| 291 |
+
— *end example*]
|
| 292 |
+
|
| 293 |
+
#### Fold expanded constraint <a id="temp.constr.fold">[[temp.constr.fold]]</a>
|
| 294 |
+
|
| 295 |
+
A *fold expanded constraint* is formed from a constraint C and a
|
| 296 |
+
*fold-operator* which can either be `&&` or `||`. A fold expanded
|
| 297 |
+
constraint is a pack expansion [[temp.variadic]]. Let N be the number of
|
| 298 |
+
elements in the pack expansion parameters [[temp.variadic]].
|
| 299 |
+
|
| 300 |
+
A fold expanded constraint whose *fold-operator* is `&&` is satisfied if
|
| 301 |
+
it is a valid pack expansion and if N = 0 or if for each i where
|
| 302 |
+
0 ≤ i < N in increasing order, C is satisfied when replacing each pack
|
| 303 |
+
expansion parameter with the corresponding iᵗʰ element. No substitution
|
| 304 |
+
takes place for any i greater than the smallest i for which the
|
| 305 |
+
constraint is not satisfied.
|
| 306 |
+
|
| 307 |
+
A fold expanded constraint whose *fold-operator* is `||` is satisfied if
|
| 308 |
+
it is a valid pack expansion, N > 0, and if for i where 0 ≤ i < N in
|
| 309 |
+
increasing order, there is a smallest i for which C is satisfied when
|
| 310 |
+
replacing each pack expansion parameter with the corresponding iᵗʰ
|
| 311 |
+
element. No substitution takes place for any i greater than the smallest
|
| 312 |
+
i for which the constraint is satisfied.
|
| 313 |
+
|
| 314 |
+
[*Note 1*: If the pack expansion expands packs of different size, then
|
| 315 |
+
it is invalid and the fold expanded constraint is not
|
| 316 |
+
satisfied. — *end note*]
|
| 317 |
+
|
| 318 |
+
Two fold expanded constraints are *compatible for subsumption* if their
|
| 319 |
+
respective constraints both contain an equivalent unexpanded pack
|
| 320 |
+
[[temp.over.link]].
|
| 321 |
+
|
| 322 |
### Constrained declarations <a id="temp.constr.decl">[[temp.constr.decl]]</a>
|
| 323 |
|
| 324 |
A template declaration [[temp.pre]] or templated function declaration
|
| 325 |
[[dcl.fct]] can be constrained by the use of a *requires-clause*. This
|
| 326 |
allows the specification of constraints for that declaration as an
|
|
|
|
| 431 |
- The normal form of an expression `( E )` is the normal form of `E`.
|
| 432 |
- The normal form of an expression `E1 || E2` is the disjunction
|
| 433 |
[[temp.constr.op]] of the normal forms of `E1` and `E2`.
|
| 434 |
- The normal form of an expression `E1 && E2` is the conjunction of the
|
| 435 |
normal forms of `E1` and `E2`.
|
| 436 |
+
- For a concept-id `C<A₁, A₂, …, Aₙ>` termed `CI`:
|
| 437 |
+
- If `C` names a dependent concept, the normal form of `CI` is a
|
| 438 |
+
concept-dependent constraint whose concept-id is `CI` and whose
|
| 439 |
+
parameter mapping is the identity mapping.
|
| 440 |
+
- Otherwise, to form `CE`, any non-dependent concept template argument
|
| 441 |
+
`Aᵢ` is substituted into the *constraint-expression* of `C`. If any
|
| 442 |
+
such substitution results in an invalid concept-id, the program is
|
| 443 |
+
ill-formed; no diagnostic is required. The normal form of `CI` is
|
| 444 |
+
the result of substituting, in the normal form `N` of `CE`,
|
| 445 |
+
appearances of `C`'s template parameters in the parameter mappings
|
| 446 |
+
of the atomic constraints in `N` with their respective arguments
|
| 447 |
+
from `C`. If any such substitution results in an invalid type or
|
| 448 |
+
expression, the program is ill-formed; no diagnostic is required.
|
| 449 |
+
|
| 450 |
\[*Example 1*:
|
| 451 |
``` cpp
|
| 452 |
template<typename T> concept A = T::value || true;
|
| 453 |
template<typename U> concept B = A<U*>;
|
| 454 |
template<typename V> concept C = B<V&>;
|
|
|
|
| 459 |
mapping), despite the expression `T::value` being ill-formed for a
|
| 460 |
pointer type `T`. Normalization of `C`'s *constraint-expression*
|
| 461 |
results in the program being ill-formed, because it would form the
|
| 462 |
invalid type `V&*` in the parameter mapping.
|
| 463 |
— *end example*]
|
| 464 |
+
- For a *fold-operator* `Op` [[expr.prim.fold]] that is either `&&` or
|
| 465 |
+
`||`:
|
| 466 |
+
- The normal form of an expression `( ... Op E )` is the normal form
|
| 467 |
+
of `( E Op ... )`.
|
| 468 |
+
- The normal form of an expression `( E1 Op ... Op E2 )` is the normal
|
| 469 |
+
form of
|
| 470 |
+
- `( E1 Op ... ) Op E2` if `E1` contains an unexpanded pack, or
|
| 471 |
+
- `E1 Op ( E2 Op ... )` otherwise.
|
| 472 |
+
- The normal form of an expression `F` of the form `( E Op ... )` is
|
| 473 |
+
as follows:
|
| 474 |
+
If `E` contains an unexpanded concept template parameter pack, it
|
| 475 |
+
shall not contain an unexpanded template parameter pack of another
|
| 476 |
+
kind. Let `E'` be the normal form of `E`.
|
| 477 |
+
- If `E` contains an unexpanded concept template parameter pack `Pₖ`
|
| 478 |
+
that has corresponding template arguments in the parameter mapping
|
| 479 |
+
of any atomic constraint (including concept-dependent constraints)
|
| 480 |
+
of `E'`, the number of arguments specified for all such `Pₖ` shall
|
| 481 |
+
be the same number N. The normal form of `F` is the normal form of
|
| 482 |
+
`E₀ Op … Op E_{N-1}` after substituting in `Eᵢ` the respective iᵗʰ
|
| 483 |
+
concept argument of each `Pₖ`. If any such substitution results in
|
| 484 |
+
an invalid type or expression, the program is ill-formed; no
|
| 485 |
+
diagnostic is required.
|
| 486 |
+
- Otherwise, the normal form of `F` is a fold expanded constraint
|
| 487 |
+
[[temp.constr.fold]] whose constraint is `E'` and whose
|
| 488 |
+
*fold-operator* is `Op`.
|
| 489 |
- The normal form of any other expression `E` is the atomic constraint
|
| 490 |
whose expression is `E` and whose parameter mapping is the identity
|
| 491 |
mapping.
|
| 492 |
|
| 493 |
The process of obtaining the normal form of a *constraint-expression* is
|
|
|
|
| 518 |
The associated constraints of \#3 are `requires (T x) { ++x; }` (with
|
| 519 |
mapping `T` ↦ `U`).
|
| 520 |
|
| 521 |
— *end example*]
|
| 522 |
|
| 523 |
+
[*Example 3*:
|
| 524 |
+
|
| 525 |
+
``` cpp
|
| 526 |
+
template<typename T>
|
| 527 |
+
concept C = true;
|
| 528 |
+
template<typename T, template<typename> concept CT>
|
| 529 |
+
concept CC = CT<T>;
|
| 530 |
+
|
| 531 |
+
template<typename U,
|
| 532 |
+
template<typename, template<typename> concept> concept CT>
|
| 533 |
+
void f() requires CT<U*, C>;
|
| 534 |
+
template<typename U>
|
| 535 |
+
void g() requires CC<U*, C>;
|
| 536 |
+
```
|
| 537 |
+
|
| 538 |
+
The normal form of the associated constraints of `f` is the
|
| 539 |
+
concept-dependent constraint `CT<T, C>`.
|
| 540 |
+
The normal form of the associated constraints of `g` is the atomic
|
| 541 |
+
constraint `true`.
|
| 542 |
+
|
| 543 |
+
— *end example*]
|
| 544 |
+
|
| 545 |
+
[*Example 4*:
|
| 546 |
+
|
| 547 |
+
``` cpp
|
| 548 |
+
template<typename T>
|
| 549 |
+
concept A = true;
|
| 550 |
+
template<typename T>
|
| 551 |
+
concept B = A<T> && true; // B subsumes A
|
| 552 |
+
template<typename T>
|
| 553 |
+
concept C = true;
|
| 554 |
+
template<typename T>
|
| 555 |
+
concept D = C<T> && true; // D subsumes C
|
| 556 |
+
|
| 557 |
+
template<typename T, template<typename> concept... CTs>
|
| 558 |
+
concept all_of = (CTs<T> && ...);
|
| 559 |
+
|
| 560 |
+
template<typename T> requires all_of<T, A, C>
|
| 561 |
+
constexpr int f(T) { return 1; } // #1
|
| 562 |
+
template<typename T> requires all_of<T, B, D>
|
| 563 |
+
constexpr int f(T) { return 2; } // #2
|
| 564 |
+
|
| 565 |
+
static_assert(f(1) == 2); // ok
|
| 566 |
+
```
|
| 567 |
+
|
| 568 |
+
The normal form of `all_of<T, A, C>` is the conjunction of the normal
|
| 569 |
+
forms of `A<T>` and `C<T>`.
|
| 570 |
+
Similarly, the normal form of `all_of<T, B, D>` is the conjunction of
|
| 571 |
+
the normal forms of `B<T>` and `D<T>`.
|
| 572 |
+
\#2 therefore is more constrained than \#1.
|
| 573 |
+
|
| 574 |
+
— *end example*]
|
| 575 |
+
|
| 576 |
+
[*Example 5*:
|
| 577 |
+
|
| 578 |
+
``` cpp
|
| 579 |
+
template<typename T, template<typename> concept>
|
| 580 |
+
struct wrapper {};
|
| 581 |
+
|
| 582 |
+
template<typename... T, template<typename> concept... CTs>
|
| 583 |
+
int f(wrapper<T, CTs>...) requires (CTs<T> && ...); // error: fold expression contains
|
| 584 |
+
// different kinds of template parameters
|
| 585 |
+
```
|
| 586 |
+
|
| 587 |
+
— *end example*]
|
| 588 |
+
|
| 589 |
### Partial ordering by constraints <a id="temp.constr.order">[[temp.constr.order]]</a>
|
| 590 |
|
| 591 |
A constraint P *subsumes* a constraint Q if and only if, for every
|
| 592 |
+
disjunctive clause Pᵢ in the disjunctive normal form[^3]
|
| 593 |
|
| 594 |
of P, Pᵢ subsumes every conjunctive clause Qⱼ in the conjunctive normal
|
| 595 |
+
form[^4]
|
| 596 |
|
| 597 |
of Q, where
|
| 598 |
|
| 599 |
- a disjunctive clause Pᵢ subsumes a conjunctive clause Qⱼ if and only
|
| 600 |
if there exists an atomic constraint Pᵢₐ in Pᵢ for which there exists
|
| 601 |
an atomic constraint $Q_{jb}$ in Qⱼ such that Pᵢₐ subsumes $Q_{jb}$,
|
|
|
|
| 602 |
- an atomic constraint A subsumes another atomic constraint B if and
|
| 603 |
only if A and B are identical using the rules described in
|
| 604 |
+
[[temp.constr.atomic]], and
|
| 605 |
+
- a fold expanded constraint A subsumes another fold expanded constraint
|
| 606 |
+
B if they are compatible for subsumption, have the same
|
| 607 |
+
*fold-operator*, and the constraint of A subsumes that of B.
|
| 608 |
|
| 609 |
[*Example 1*: Let A and B be atomic constraints [[temp.constr.atomic]].
|
| 610 |
The constraint A ∧ B subsumes A, but A does not subsume A ∧ B. The
|
| 611 |
constraint A subsumes A ∨ B, but A ∨ B does not subsume A. Also note
|
| 612 |
that every constraint subsumes itself. — *end example*]
|
|
|
|
| 624 |
[[temp.spec.partial.order]], and
|
| 625 |
- the partial ordering of function templates [[temp.func.order]].
|
| 626 |
|
| 627 |
— *end note*]
|
| 628 |
|
| 629 |
+
The associated constraints `C` of a declaration `D` are *eligible for
|
| 630 |
+
subsumption* unless `C` contains a concept-dependent constraint.
|
| 631 |
+
|
| 632 |
A declaration `D1` is *at least as constrained* as a declaration `D2` if
|
| 633 |
|
| 634 |
- `D1` and `D2` are both constrained declarations and `D1`’s associated
|
| 635 |
+
constraints are eligible for subsumption and subsume those of `D2`; or
|
| 636 |
- `D2` has no associated constraints.
|
| 637 |
|
| 638 |
A declaration `D1` is *more constrained* than another declaration `D2`
|
| 639 |
when `D1` is at least as constrained as `D2`, and `D2` is not at least
|
| 640 |
as constrained as `D1`.
|
|
|
|
| 656 |
g(0); // selects #4
|
| 657 |
```
|
| 658 |
|
| 659 |
— *end example*]
|
| 660 |
|
| 661 |
+
[*Example 3*:
|
| 662 |
+
|
| 663 |
+
``` cpp
|
| 664 |
+
template<template<typename T> concept CT, typename T>
|
| 665 |
+
struct S {};
|
| 666 |
+
template<typename T>
|
| 667 |
+
concept A = true;
|
| 668 |
+
|
| 669 |
+
template<template<typename T> concept X, typename T>
|
| 670 |
+
int f(S<X, T>) requires A<T> { return 42; } // #1
|
| 671 |
+
template<template<typename T> concept X, typename T>
|
| 672 |
+
int f(S<X, T>) requires X<T> { return 43; } // #2
|
| 673 |
+
|
| 674 |
+
f(S<A, int>{}); // ok, select #1 because #2 is not eligible for subsumption
|
| 675 |
+
```
|
| 676 |
+
|
| 677 |
+
— *end example*]
|
| 678 |
+
|
| 679 |
+
A non-template function `F1` is *more partial-ordering-constrained* than
|
| 680 |
+
a non-template function `F2` if
|
| 681 |
+
|
| 682 |
+
- they have the same non-object-parameter-type-lists [[dcl.fct]], and
|
| 683 |
+
- if they are member functions, both are direct members of the same
|
| 684 |
+
class, and
|
| 685 |
+
- if both are non-static member functions, they have the same types for
|
| 686 |
+
their object parameters, and
|
| 687 |
+
- the declaration of `F1` is more constrained than the declaration of
|
| 688 |
+
`F2`.
|
| 689 |
+
|