From Jason Turner

[concepts.lang]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp2f6mv8k3/{from.md → to.md} +25 -21
tmp/tmp2f6mv8k3/{from.md → to.md} RENAMED
@@ -33,22 +33,22 @@ template<class Derived, class Base>
33
  `Derived` and `Base` are the same class type ignoring
34
  cv-qualifiers. — *end note*]
35
 
36
  ### Concept <a id="concept.convertible">[[concept.convertible]]</a>
37
 
38
- Given types `From` and `To` and an expression `E` such that
39
- `decltype((E))` is `add_rvalue_reference_t<From>`,
40
  `convertible_to<From, To>` requires `E` to be both implicitly and
41
  explicitly convertible to type `To`. The implicit and explicit
42
  conversions are required to produce equal results.
43
 
44
  ``` cpp
45
  template<class From, class To>
46
  concept convertible_to =
47
  is_convertible_v<From, To> &&
48
- requires(add_rvalue_reference_t<From> (&f)()) {
49
- static_cast<To>(f());
50
  };
51
  ```
52
 
53
  Let `FromR` be `add_rvalue_reference_t<From>` and `test` be the invented
54
  function:
@@ -77,12 +77,12 @@ that `f()` is equality-preserving. Types `From` and `To` model
77
  For two types `T` and `U`, if `common_reference_t<T, U>` is well-formed
78
  and denotes a type `C` such that both `convertible_to<T, C>` and
79
  `convertible_to<U, C>` are modeled, then `T` and `U` share a *common
80
  reference type*, `C`.
81
 
82
- [*Note 1*: `C` could be the same as `T`, or `U`, or it could be a
83
- different type. `C` may be a reference type. — *end note*]
84
 
85
  ``` cpp
86
  template<class T, class U>
87
  concept common_reference_with =
88
  same_as<common_reference_t<T, U>, common_reference_t<U, T>> &&
@@ -107,12 +107,12 @@ template [[meta.trans.other]]. — *end note*]
107
  ### Concept <a id="concept.common">[[concept.common]]</a>
108
 
109
  If `T` and `U` can both be explicitly converted to some third type, `C`,
110
  then `T` and `U` share a *common type*, `C`.
111
 
112
- [*Note 1*: `C` could be the same as `T`, or `U`, or it could be a
113
- different type. `C` might not be unique. — *end note*]
114
 
115
  ``` cpp
116
  template<class T, class U>
117
  concept common_with =
118
  same_as<common_type_t<T, U>, common_type_t<U, T>> &&
@@ -223,31 +223,35 @@ if the operation modifies neither `t2` nor `u2` and:
223
  The name `ranges::swap` denotes a customization point object
224
  [[customization.point.object]]. The expression `ranges::swap(E1, E2)`
225
  for subexpressions `E1` and `E2` is expression-equivalent to an
226
  expression `S` determined as follows:
227
 
228
- - `S` is `(void)swap(E1, E2)`[^1] if `E1` or `E2` has class or
229
- enumeration type [[basic.compound]] and that expression is valid, with
230
- overload resolution performed in a context that includes the
231
- declaration
232
  ``` cpp
233
  template<class T>
234
  void swap(T&, T&) = delete;
235
  ```
236
 
237
  and does not include a declaration of `ranges::swap`. If the function
238
  selected by overload resolution does not exchange the values denoted
239
  by `E1` and `E2`, the program is ill-formed, no diagnostic required.
 
 
 
 
240
  - Otherwise, if `E1` and `E2` are lvalues of array types
241
  [[basic.compound]] with equal extent and `ranges::swap(*E1, *E2)` is a
242
  valid expression, `S` is `(void)ranges::swap_ranges(E1, E2)`, except
243
  that `noexcept(S)` is equal to `noexcept({}ranges::swap(*E1, *E2))`.
244
  - Otherwise, if `E1` and `E2` are lvalues of the same type `T` that
245
  models `move_constructible<T>` and `assignable_from<T&, T>`, `S` is an
246
  expression that exchanges the denoted values. `S` is a constant
247
  expression if
248
- - `T` is a literal type [[basic.types]],
249
  - both `E1 = std::move(E2)` and `E2 = std::move(E1)` are constant
250
  subexpressions [[defns.const.subexpr]], and
251
  - the full-expressions of the initializers in the declarations
252
  ``` cpp
253
  T t1(std::move(E1));
@@ -256,15 +260,15 @@ expression `S` determined as follows:
256
 
257
  are constant subexpressions.
258
 
259
  `noexcept(S)` is equal to
260
  `is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>`.
261
- - Otherwise, `ranges::swap(E1, E2)` is ill-formed. \[*Note 2*: This case
262
  can result in substitution failure when `ranges::swap(E1, E2)` appears
263
  in the immediate context of a template instantiation. — *end note*]
264
 
265
- [*Note 3*: Whenever `ranges::swap(E1, E2)` is a valid expression, it
266
  exchanges the values denoted by `E1` and `E2` and has type
267
  `void`. — *end note*]
268
 
269
  ``` cpp
270
  template<class T>
@@ -281,13 +285,13 @@ template<class T, class U>
281
  ranges::swap(std::forward<T>(t), std::forward<U>(u));
282
  ranges::swap(std::forward<U>(u), std::forward<T>(t));
283
  };
284
  ```
285
 
286
- [*Note 4*: The semantics of the `swappable` and `swappable_with`
287
- concepts are fully defined by the `ranges::swap` customization
288
- point. — *end note*]
289
 
290
  [*Example 1*:
291
 
292
  User code can ensure that the evaluation of `swap` calls is performed in
293
  an appropriate context under the various conditions as follows:
@@ -362,11 +366,11 @@ template<class T, class... Args>
362
 
363
  ### Concept <a id="concept.default.init">[[concept.default.init]]</a>
364
 
365
  ``` cpp
366
  template<class T>
367
- inline constexpr bool is-default-initializable = see below; // exposition only
368
 
369
  template<class T>
370
  concept default_initializable = constructible_from<T> &&
371
  requires { T{}; } &&
372
  is-default-initializable<T>;
@@ -409,12 +413,12 @@ template<class T>
409
  constructible_from<T, T&> && convertible_to<T&, T> &&
410
  constructible_from<T, const T&> && convertible_to<const T&, T> &&
411
  constructible_from<T, const T> && convertible_to<const T, T>;
412
  ```
413
 
414
- If `T` is an object type, then let `v` be an lvalue of type (possibly
415
- `const`) `T` or an rvalue of type `const T`. `T` models
416
  `copy_constructible` only if
417
 
418
  - After the definition `T u = v;`, `u` is equal to `v`
419
  [[concepts.equality]] and `v` is not modified.
420
  - `T(v)` is equal to `v` and does not modify `v`.
 
33
  `Derived` and `Base` are the same class type ignoring
34
  cv-qualifiers. — *end note*]
35
 
36
  ### Concept <a id="concept.convertible">[[concept.convertible]]</a>
37
 
38
+ Given types `From` and `To` and an expression `E` whose type and value
39
+ category are the same as those of `declval<From>()`,
40
  `convertible_to<From, To>` requires `E` to be both implicitly and
41
  explicitly convertible to type `To`. The implicit and explicit
42
  conversions are required to produce equal results.
43
 
44
  ``` cpp
45
  template<class From, class To>
46
  concept convertible_to =
47
  is_convertible_v<From, To> &&
48
+ requires {
49
+ static_cast<To>(declval<From>());
50
  };
51
  ```
52
 
53
  Let `FromR` be `add_rvalue_reference_t<From>` and `test` be the invented
54
  function:
 
77
  For two types `T` and `U`, if `common_reference_t<T, U>` is well-formed
78
  and denotes a type `C` such that both `convertible_to<T, C>` and
79
  `convertible_to<U, C>` are modeled, then `T` and `U` share a *common
80
  reference type*, `C`.
81
 
82
+ [*Note 1*: `C` can be the same as `T` or `U`, or can be a different
83
+ type. `C` can be a reference type. — *end note*]
84
 
85
  ``` cpp
86
  template<class T, class U>
87
  concept common_reference_with =
88
  same_as<common_reference_t<T, U>, common_reference_t<U, T>> &&
 
107
  ### Concept <a id="concept.common">[[concept.common]]</a>
108
 
109
  If `T` and `U` can both be explicitly converted to some third type, `C`,
110
  then `T` and `U` share a *common type*, `C`.
111
 
112
+ [*Note 1*: `C` can be the same as `T` or `U`, or can be a different
113
+ type. `C` is not necessarily unique. — *end note*]
114
 
115
  ``` cpp
116
  template<class T, class U>
117
  concept common_with =
118
  same_as<common_type_t<T, U>, common_type_t<U, T>> &&
 
223
  The name `ranges::swap` denotes a customization point object
224
  [[customization.point.object]]. The expression `ranges::swap(E1, E2)`
225
  for subexpressions `E1` and `E2` is expression-equivalent to an
226
  expression `S` determined as follows:
227
 
228
+ - `S` is `(void)swap(E1, E2)`[^1]
229
+ if `E1` or `E2` has class or enumeration type [[basic.compound]] and
230
+ that expression is valid, with overload resolution performed in a
231
+ context that includes the declaration
232
  ``` cpp
233
  template<class T>
234
  void swap(T&, T&) = delete;
235
  ```
236
 
237
  and does not include a declaration of `ranges::swap`. If the function
238
  selected by overload resolution does not exchange the values denoted
239
  by `E1` and `E2`, the program is ill-formed, no diagnostic required.
240
+ \[*Note 2*: This precludes calling unconstrained program-defined
241
+ overloads of `swap`. When the deleted overload is viable,
242
+ program-defined overloads need to be more specialized
243
+ [[temp.func.order]] to be selected. — *end note*]
244
  - Otherwise, if `E1` and `E2` are lvalues of array types
245
  [[basic.compound]] with equal extent and `ranges::swap(*E1, *E2)` is a
246
  valid expression, `S` is `(void)ranges::swap_ranges(E1, E2)`, except
247
  that `noexcept(S)` is equal to `noexcept({}ranges::swap(*E1, *E2))`.
248
  - Otherwise, if `E1` and `E2` are lvalues of the same type `T` that
249
  models `move_constructible<T>` and `assignable_from<T&, T>`, `S` is an
250
  expression that exchanges the denoted values. `S` is a constant
251
  expression if
252
+ - `T` is a literal type [[term.literal.type]],
253
  - both `E1 = std::move(E2)` and `E2 = std::move(E1)` are constant
254
  subexpressions [[defns.const.subexpr]], and
255
  - the full-expressions of the initializers in the declarations
256
  ``` cpp
257
  T t1(std::move(E1));
 
260
 
261
  are constant subexpressions.
262
 
263
  `noexcept(S)` is equal to
264
  `is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>`.
265
+ - Otherwise, `ranges::swap(E1, E2)` is ill-formed. \[*Note 3*: This case
266
  can result in substitution failure when `ranges::swap(E1, E2)` appears
267
  in the immediate context of a template instantiation. — *end note*]
268
 
269
+ [*Note 4*: Whenever `ranges::swap(E1, E2)` is a valid expression, it
270
  exchanges the values denoted by `E1` and `E2` and has type
271
  `void`. — *end note*]
272
 
273
  ``` cpp
274
  template<class T>
 
285
  ranges::swap(std::forward<T>(t), std::forward<U>(u));
286
  ranges::swap(std::forward<U>(u), std::forward<T>(t));
287
  };
288
  ```
289
 
290
+ [*Note 5*: The semantics of the `swappable` and `swappable_with`
291
+ concepts are fully defined by the `ranges::swap` customization point
292
+ object. — *end note*]
293
 
294
  [*Example 1*:
295
 
296
  User code can ensure that the evaluation of `swap` calls is performed in
297
  an appropriate context under the various conditions as follows:
 
366
 
367
  ### Concept <a id="concept.default.init">[[concept.default.init]]</a>
368
 
369
  ``` cpp
370
  template<class T>
371
+ constexpr bool is-default-initializable = see below; // exposition only
372
 
373
  template<class T>
374
  concept default_initializable = constructible_from<T> &&
375
  requires { T{}; } &&
376
  is-default-initializable<T>;
 
413
  constructible_from<T, T&> && convertible_to<T&, T> &&
414
  constructible_from<T, const T&> && convertible_to<const T&, T> &&
415
  constructible_from<T, const T> && convertible_to<const T, T>;
416
  ```
417
 
418
+ If `T` is an object type, then let `v` be an lvalue of type `T` or
419
+ `const T` or an rvalue of type `const T`. `T` models
420
  `copy_constructible` only if
421
 
422
  - After the definition `T u = v;`, `u` is equal to `v`
423
  [[concepts.equality]] and `v` is not modified.
424
  - `T(v)` is equal to `v` and does not modify `v`.