From Jason Turner

[concepts.lang]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmps1qh905x/{from.md → to.md} +421 -0
tmp/tmps1qh905x/{from.md → to.md} RENAMED
@@ -0,0 +1,421 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Language-related concepts <a id="concepts.lang">[[concepts.lang]]</a>
2
+
3
+ ### General <a id="concepts.lang.general">[[concepts.lang.general]]</a>
4
+
5
+ Subclause [[concepts.lang]] contains the definition of concepts
6
+ corresponding to language features. These concepts express relationships
7
+ between types, type classifications, and fundamental type properties.
8
+
9
+ ### Concept <a id="concept.same">[[concept.same]]</a>
10
+
11
+ ``` cpp
12
+ template<class T, class U>
13
+ concept same-as-impl = is_same_v<T, U>; // exposition only
14
+
15
+ template<class T, class U>
16
+ concept same_as = same-as-impl<T, U> && same-as-impl<U, T>;
17
+ ```
18
+
19
+ [*Note 1*: `same_as<T, U>` subsumes `same_as<U, T>` and vice
20
+ versa. — *end note*]
21
+
22
+ ### Concept <a id="concept.derived">[[concept.derived]]</a>
23
+
24
+ ``` cpp
25
+ template<class Derived, class Base>
26
+ concept derived_from =
27
+ is_base_of_v<Base, Derived> &&
28
+ is_convertible_v<const volatile Derived*, const volatile Base*>;
29
+ ```
30
+
31
+ [*Note 1*: `derived_from<Derived, Base>` is satisfied if and only if
32
+ `Derived` is publicly and unambiguously derived from `Base`, or
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:
55
+
56
+ ``` cpp
57
+ To test(FromR (&f)()) {
58
+ return f();
59
+ }
60
+ ```
61
+
62
+ and let `f` be a function with no arguments and return type `FromR` such
63
+ that `f()` is equality-preserving. Types `From` and `To` model
64
+ `convertible_to<From, To>` only if:
65
+
66
+ - `To` is not an object or reference-to-object type, or
67
+ `static_cast<To>(f())` is equal to `test(f)`.
68
+ - `FromR` is not a reference-to-object type, or
69
+ - If `FromR` is an rvalue reference to a non const-qualified type, the
70
+ resulting state of the object referenced by `f()` after either above
71
+ expression is valid but unspecified [[lib.types.movedfrom]].
72
+ - Otherwise, the object referred to by `f()` is not modified by either
73
+ above expression.
74
+
75
+ ### Concept <a id="concept.commonref">[[concept.commonref]]</a>
76
+
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>> &&
89
+ convertible_to<T, common_reference_t<T, U>> &&
90
+ convertible_to<U, common_reference_t<T, U>>;
91
+ ```
92
+
93
+ Let `C` be `common_reference_t<T, U>`. Let `t1` and `t2` be
94
+ equality-preserving expressions [[concepts.equality]] such that
95
+ `decltype((t1))` and `decltype((t2))` are each `T`, and let `u1` and
96
+ `u2` be equality-preserving expressions such that `decltype((u1))` and
97
+ `decltype((u2))` are each `U`. `T` and `U` model
98
+ `common_reference_with<T, U>` only if:
99
+
100
+ - `C(t1)` equals `C(t2)` if and only if `t1` equals `t2`, and
101
+ - `C(u1)` equals `C(u2)` if and only if `u1` equals `u2`.
102
+
103
+ [*Note 1*: Users can customize the behavior of `common_reference_with`
104
+ by specializing the `basic_common_reference` class
105
+ template [[meta.trans.other]]. — *end note*]
106
+
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>> &&
119
+ requires {
120
+ static_cast<common_type_t<T, U>>(declval<T>());
121
+ static_cast<common_type_t<T, U>>(declval<U>());
122
+ } &&
123
+ common_reference_with<
124
+ add_lvalue_reference_t<const T>,
125
+ add_lvalue_reference_t<const U>> &&
126
+ common_reference_with<
127
+ add_lvalue_reference_t<common_type_t<T, U>>,
128
+ common_reference_t<
129
+ add_lvalue_reference_t<const T>,
130
+ add_lvalue_reference_t<const U>>>;
131
+ ```
132
+
133
+ Let `C` be `common_type_t<T, U>`. Let `t1` and `t2` be
134
+ equality-preserving expressions [[concepts.equality]] such that
135
+ `decltype((t1))` and `decltype((t2))` are each `T`, and let `u1` and
136
+ `u2` be equality-preserving expressions such that `decltype((u1))` and
137
+ `decltype((u2))` are each `U`. `T` and `U` model `common_with<T, U>`
138
+ only if:
139
+
140
+ - `C(t1)` equals `C(t2)` if and only if `t1` equals `t2`, and
141
+ - `C(u1)` equals `C(u2)` if and only if `u1` equals `u2`.
142
+
143
+ [*Note 1*: Users can customize the behavior of `common_with` by
144
+ specializing the `common_type` class
145
+ template [[meta.trans.other]]. — *end note*]
146
+
147
+ ### Arithmetic concepts <a id="concepts.arithmetic">[[concepts.arithmetic]]</a>
148
+
149
+ ``` cpp
150
+ template<class T>
151
+ concept integral = is_integral_v<T>;
152
+ template<class T>
153
+ concept signed_integral = integral<T> && is_signed_v<T>;
154
+ template<class T>
155
+ concept unsigned_integral = integral<T> && !signed_integral<T>;
156
+ template<class T>
157
+ concept floating_point = is_floating_point_v<T>;
158
+ ```
159
+
160
+ [*Note 1*: `signed_integral` can be modeled even by types that are not
161
+ signed integer types [[basic.fundamental]]; for example,
162
+ `char`. — *end note*]
163
+
164
+ [*Note 2*: `unsigned_integral` can be modeled even by types that are
165
+ not unsigned integer types [[basic.fundamental]]; for example,
166
+ `bool`. — *end note*]
167
+
168
+ ### Concept <a id="concept.assignable">[[concept.assignable]]</a>
169
+
170
+ ``` cpp
171
+ template<class LHS, class RHS>
172
+ concept assignable_from =
173
+ is_lvalue_reference_v<LHS> &&
174
+ common_reference_with<const remove_reference_t<LHS>&, const remove_reference_t<RHS>&> &&
175
+ requires(LHS lhs, RHS&& rhs) {
176
+ { lhs = std::forward<RHS>(rhs) } -> same_as<LHS>;
177
+ };
178
+ ```
179
+
180
+ Let:
181
+
182
+ - `lhs` be an lvalue that refers to an object `lcopy` such that
183
+ `decltype((lhs))` is `LHS`,
184
+ - `rhs` be an expression such that `decltype((rhs))` is `RHS`, and
185
+ - `rcopy` be a distinct object that is equal to `rhs`.
186
+
187
+ `LHS` and `RHS` model `assignable_from<LHS, RHS>` only if
188
+
189
+ - `addressof(lhs = rhs) == addressof(lcopy)`.
190
+ - After evaluating `lhs = rhs`:
191
+ - `lhs` is equal to `rcopy`, unless `rhs` is a non-const xvalue that
192
+ refers to `lcopy`.
193
+ - If `rhs` is a non-`const` xvalue, the resulting state of the object
194
+ to which it refers is valid but unspecified [[lib.types.movedfrom]].
195
+ - Otherwise, if `rhs` is a glvalue, the object to which it refers is
196
+ not modified.
197
+
198
+ [*Note 1*: Assignment need not be a total
199
+ function [[structure.requirements]]; in particular, if assignment to an
200
+ object `x` can result in a modification of some other object `y`, then
201
+ `x = y` is likely not in the domain of `=`. — *end note*]
202
+
203
+ ### Concept <a id="concept.swappable">[[concept.swappable]]</a>
204
+
205
+ Let `t1` and `t2` be equality-preserving expressions that denote
206
+ distinct equal objects of type `T`, and let `u1` and `u2` similarly
207
+ denote distinct equal objects of type `U`.
208
+
209
+ [*Note 1*: `t1` and `u1` can denote distinct objects, or the same
210
+ object. — *end note*]
211
+
212
+ An operation *exchanges the values* denoted by `t1` and `u1` if and only
213
+ if the operation modifies neither `t2` nor `u2` and:
214
+
215
+ - If `T` and `U` are the same type, the result of the operation is that
216
+ `t1` equals `u2` and `u1` equals `t2`.
217
+ - If `T` and `U` are different types and
218
+ `common_reference_with<decltype((t1)), decltype((u1))>` is modeled,
219
+ the result of the operation is that `C(t1)` equals `C(u2)` and `C(u1)`
220
+ equals `C(t2)` where `C` is
221
+ `common_reference_t<decltype((t1)), decltype((u1))>`.
222
+
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));
254
+ T t2(std::move(E2));
255
+ ```
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>
271
+ concept swappable = requires(T& a, T& b) { ranges::swap(a, b); };
272
+ ```
273
+
274
+ ``` cpp
275
+ template<class T, class U>
276
+ concept swappable_with =
277
+ common_reference_with<T, U> &&
278
+ requires(T&& t, U&& u) {
279
+ ranges::swap(std::forward<T>(t), std::forward<T>(t));
280
+ ranges::swap(std::forward<U>(u), std::forward<U>(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:
294
+
295
+ ``` cpp
296
+ #include <cassert>
297
+ #include <concepts>
298
+ #include <utility>
299
+
300
+ namespace ranges = std::ranges;
301
+
302
+ template<class T, std::swappable_with<T> U>
303
+ void value_swap(T&& t, U&& u) {
304
+ ranges::swap(std::forward<T>(t), std::forward<U>(u));
305
+ }
306
+
307
+ template<std::swappable T>
308
+ void lv_swap(T& t1, T& t2) {
309
+ ranges::swap(t1, t2);
310
+ }
311
+
312
+ namespace N {
313
+ struct A { int m; };
314
+ struct Proxy {
315
+ A* a;
316
+ Proxy(A& a) : a{&a} {}
317
+ friend void swap(Proxy x, Proxy y) {
318
+ ranges::swap(*x.a, *y.a);
319
+ }
320
+ };
321
+ Proxy proxy(A& a) { return Proxy{ a }; }
322
+ }
323
+
324
+ int main() {
325
+ int i = 1, j = 2;
326
+ lv_swap(i, j);
327
+ assert(i == 2 && j == 1);
328
+
329
+ N::A a1 = { 5 }, a2 = { -5 };
330
+ value_swap(a1, proxy(a2));
331
+ assert(a1.m == -5 && a2.m == 5);
332
+ }
333
+ ```
334
+
335
+ — *end example*]
336
+
337
+ ### Concept <a id="concept.destructible">[[concept.destructible]]</a>
338
+
339
+ The `destructible` concept specifies properties of all types, instances
340
+ of which can be destroyed at the end of their lifetime, or reference
341
+ types.
342
+
343
+ ``` cpp
344
+ template<class T>
345
+ concept destructible = is_nothrow_destructible_v<T>;
346
+ ```
347
+
348
+ [*Note 1*: Unlike the *Cpp17Destructible*
349
+ requirements ([[cpp17.destructible]]), this concept forbids destructors
350
+ that are potentially throwing, even if a particular invocation of the
351
+ destructor does not actually throw. — *end note*]
352
+
353
+ ### Concept <a id="concept.constructible">[[concept.constructible]]</a>
354
+
355
+ The `constructible_from` concept constrains the initialization of a
356
+ variable of a given type with a particular set of argument types.
357
+
358
+ ``` cpp
359
+ template<class T, class... Args>
360
+ concept constructible_from = destructible<T> && is_constructible_v<T, Args...>;
361
+ ```
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>;
373
+ ```
374
+
375
+ For a type `T`, *`is-default-initializable`*`<T>` is `true` if and only
376
+ if the variable definition
377
+
378
+ ``` cpp
379
+ T t;
380
+ ```
381
+
382
+ is well-formed for some invented variable `t`; otherwise it is `false`.
383
+ Access checking is performed as if in a context unrelated to `T`. Only
384
+ the validity of the immediate context of the variable initialization is
385
+ considered.
386
+
387
+ ### Concept <a id="concept.moveconstructible">[[concept.moveconstructible]]</a>
388
+
389
+ ``` cpp
390
+ template<class T>
391
+ concept move_constructible = constructible_from<T, T> && convertible_to<T, T>;
392
+ ```
393
+
394
+ If `T` is an object type, then let `rv` be an rvalue of type `T` and
395
+ `u2` a distinct object of type `T` equal to `rv`. `T` models
396
+ `move_constructible` only if
397
+
398
+ - After the definition `T u = rv;`, `u` is equal to `u2`.
399
+ - `T(rv)` is equal to `u2`.
400
+ - If `T` is not `const`, `rv`’s resulting state is valid but
401
+ unspecified [[lib.types.movedfrom]]; otherwise, it is unchanged.
402
+
403
+ ### Concept <a id="concept.copyconstructible">[[concept.copyconstructible]]</a>
404
+
405
+ ``` cpp
406
+ template<class T>
407
+ concept copy_constructible =
408
+ move_constructible<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`.
421
+