From Jason Turner

[expected.void]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpvf9db1_h/{from.md → to.md} +634 -0
tmp/tmpvf9db1_h/{from.md → to.md} RENAMED
@@ -0,0 +1,634 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Partial specialization of `expected` for `void` types <a id="expected.void">[[expected.void]]</a>
2
+
3
+ #### General <a id="expected.void.general">[[expected.void.general]]</a>
4
+
5
+ ``` cpp
6
+ template<class T, class E> requires is_void_v<T>
7
+ class expected<T, E> {
8
+ public:
9
+ using value_type = T;
10
+ using error_type = E;
11
+ using unexpected_type = unexpected<E>;
12
+
13
+ template<class U>
14
+ using rebind = expected<U, error_type>;
15
+
16
+ // [expected.void.cons], constructors
17
+ constexpr expected() noexcept;
18
+ constexpr expected(const expected&);
19
+ constexpr expected(expected&&) noexcept(see below);
20
+ template<class U, class G>
21
+ constexpr explicit(see below) expected(const expected<U, G>&);
22
+ template<class U, class G>
23
+ constexpr explicit(see below) expected(expected<U, G>&&);
24
+
25
+ template<class G>
26
+ constexpr explicit(see below) expected(const unexpected<G>&);
27
+ template<class G>
28
+ constexpr explicit(see below) expected(unexpected<G>&&);
29
+
30
+ constexpr explicit expected(in_place_t) noexcept;
31
+ template<class... Args>
32
+ constexpr explicit expected(unexpect_t, Args&&...);
33
+ template<class U, class... Args>
34
+ constexpr explicit expected(unexpect_t, initializer_list<U>, Args&&...);
35
+
36
+
37
+ // [expected.void.dtor], destructor
38
+ constexpr ~expected();
39
+
40
+ // [expected.void.assign], assignment
41
+ constexpr expected& operator=(const expected&);
42
+ constexpr expected& operator=(expected&&) noexcept(see below);
43
+ template<class G>
44
+ constexpr expected& operator=(const unexpected<G>&);
45
+ template<class G>
46
+ constexpr expected& operator=(unexpected<G>&&);
47
+ constexpr void emplace() noexcept;
48
+
49
+ // [expected.void.swap], swap
50
+ constexpr void swap(expected&) noexcept(see below);
51
+ friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
52
+
53
+ // [expected.void.obs], observers
54
+ constexpr explicit operator bool() const noexcept;
55
+ constexpr bool has_value() const noexcept;
56
+ constexpr void operator*() const noexcept;
57
+ constexpr void value() const &;
58
+ constexpr void value() &&;
59
+ constexpr const E& error() const & noexcept;
60
+ constexpr E& error() & noexcept;
61
+ constexpr const E&& error() const && noexcept;
62
+ constexpr E&& error() && noexcept;
63
+ template<class G = E> constexpr E error_or(G&&) const &;
64
+ template<class G = E> constexpr E error_or(G&&) &&;
65
+
66
+ // [expected.void.monadic], monadic operations
67
+ template<class F> constexpr auto and_then(F&& f) &;
68
+ template<class F> constexpr auto and_then(F&& f) &&;
69
+ template<class F> constexpr auto and_then(F&& f) const &;
70
+ template<class F> constexpr auto and_then(F&& f) const &&;
71
+ template<class F> constexpr auto or_else(F&& f) &;
72
+ template<class F> constexpr auto or_else(F&& f) &&;
73
+ template<class F> constexpr auto or_else(F&& f) const &;
74
+ template<class F> constexpr auto or_else(F&& f) const &&;
75
+ template<class F> constexpr auto transform(F&& f) &;
76
+ template<class F> constexpr auto transform(F&& f) &&;
77
+ template<class F> constexpr auto transform(F&& f) const &;
78
+ template<class F> constexpr auto transform(F&& f) const &&;
79
+ template<class F> constexpr auto transform_error(F&& f) &;
80
+ template<class F> constexpr auto transform_error(F&& f) &&;
81
+ template<class F> constexpr auto transform_error(F&& f) const &;
82
+ template<class F> constexpr auto transform_error(F&& f) const &&;
83
+
84
+ // [expected.void.eq], equality operators
85
+ template<class T2, class E2> requires is_void_v<T2>
86
+ friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
87
+ template<class E2>
88
+ friend constexpr bool operator==(const expected&, const unexpected<E2>&);
89
+
90
+ private:
91
+ bool has_val; // exposition only
92
+ union {
93
+ E unex; // exposition only
94
+ };
95
+ };
96
+ ```
97
+
98
+ Any object of type `expected<T, E>` either represents a value of type
99
+ `T`, or contains a value of type `E` within its own storage.
100
+ Implementations are not permitted to use additional storage, such as
101
+ dynamic memory, to allocate the object of type `E`. Member *`has_val`*
102
+ indicates whether the `expected<T, E>` object represents a value of type
103
+ `T`.
104
+
105
+ A program that instantiates the definition of the template
106
+ `expected<T, E>` with a type for the `E` parameter that is not a valid
107
+ template argument for `unexpected` is ill-formed.
108
+
109
+ `E` shall meet the requirements of *Cpp17Destructible* (
110
+ [[cpp17.destructible]]).
111
+
112
+ #### Constructors <a id="expected.void.cons">[[expected.void.cons]]</a>
113
+
114
+ ``` cpp
115
+ constexpr expected() noexcept;
116
+ ```
117
+
118
+ *Ensures:* `has_value()` is `true`.
119
+
120
+ ``` cpp
121
+ constexpr expected(const expected& rhs);
122
+ ```
123
+
124
+ *Effects:* If `rhs.has_value()` is `false`, direct-non-list-initializes
125
+ *unex* with `rhs.error()`.
126
+
127
+ *Ensures:* `rhs.has_value() == this->has_value()`.
128
+
129
+ *Throws:* Any exception thrown by the initialization of *unex*.
130
+
131
+ *Remarks:* This constructor is defined as deleted unless
132
+ `is_copy_constructible_v<E>` is `true`.
133
+
134
+ This constructor is trivial if `is_trivially_copy_constructible_v<E>` is
135
+ `true`.
136
+
137
+ ``` cpp
138
+ constexpr expected(expected&& rhs) noexcept(is_nothrow_move_constructible_v<E>);
139
+ ```
140
+
141
+ *Constraints:* `is_move_constructible_v<E>` is `true`.
142
+
143
+ *Effects:* If `rhs.has_value()` is `false`, direct-non-list-initializes
144
+ *unex* with `std::move(rhs.error())`.
145
+
146
+ *Ensures:* `rhs.has_value()` is unchanged;
147
+ `rhs.has_value() == this->has_value()` is `true`.
148
+
149
+ *Throws:* Any exception thrown by the initialization of *unex*.
150
+
151
+ *Remarks:* This constructor is trivial if
152
+ `is_trivially_move_constructible_v<E>` is `true`.
153
+
154
+ ``` cpp
155
+ template<class U, class G>
156
+ constexpr explicit(!is_convertible_v<const G&, E>) expected(const expected<U, G>& rhs);
157
+ template<class U, class G>
158
+ constexpr explicit(!is_convertible_v<G, E>) expected(expected<U, G>&& rhs);
159
+ ```
160
+
161
+ Let `GF` be `const G&` for the first overload and `G` for the second
162
+ overload.
163
+
164
+ *Constraints:*
165
+
166
+ - `is_void_v<U>` is `true`; and
167
+ - `is_constructible_v<E, GF>` is `true`; and
168
+ - `is_constructible_v<unexpected<E>, expected<U, G>&>` is `false`; and
169
+ - `is_constructible_v<unexpected<E>, expected<U, G>>` is `false`; and
170
+ - `is_constructible_v<unexpected<E>, const expected<U, G>&>` is `false`;
171
+ and
172
+ - `is_constructible_v<unexpected<E>, const expected<U, G>>` is `false`.
173
+
174
+ *Effects:* If `rhs.has_value()` is `false`, direct-non-list-initializes
175
+ *unex* with `std::forward<GF>(rhs.error())`.
176
+
177
+ *Ensures:* `rhs.has_value()` is unchanged;
178
+ `rhs.has_value() == this->has_value()` is `true`.
179
+
180
+ *Throws:* Any exception thrown by the initialization of *unex*.
181
+
182
+ ``` cpp
183
+ template<class G>
184
+ constexpr explicit(!is_convertible_v<const G&, E>) expected(const unexpected<G>& e);
185
+ template<class G>
186
+ constexpr explicit(!is_convertible_v<G, E>) expected(unexpected<G>&& e);
187
+ ```
188
+
189
+ Let `GF` be `const G&` for the first overload and `G` for the second
190
+ overload.
191
+
192
+ *Constraints:* `is_constructible_v<E, GF>` is `true`.
193
+
194
+ *Effects:* Direct-non-list-initializes *unex* with
195
+ `std::forward<GF>(e.error())`.
196
+
197
+ *Ensures:* `has_value()` is `false`.
198
+
199
+ *Throws:* Any exception thrown by the initialization of *unex*.
200
+
201
+ ``` cpp
202
+ constexpr explicit expected(in_place_t) noexcept;
203
+ ```
204
+
205
+ *Ensures:* `has_value()` is `true`.
206
+
207
+ ``` cpp
208
+ template<class... Args>
209
+ constexpr explicit expected(unexpect_t, Args&&... args);
210
+ ```
211
+
212
+ *Constraints:* `is_constructible_v<E, Args...>` is `true`.
213
+
214
+ *Effects:* Direct-non-list-initializes *unex* with
215
+ `std::forward<Args>(args)...`.
216
+
217
+ *Ensures:* `has_value()` is `false`.
218
+
219
+ *Throws:* Any exception thrown by the initialization of *unex*.
220
+
221
+ ``` cpp
222
+ template<class U, class... Args>
223
+ constexpr explicit expected(unexpect_t, initializer_list<U> il, Args&&... args);
224
+ ```
225
+
226
+ *Constraints:* `is_constructible_v<E, initializer_list<U>&, Args...>` is
227
+ `true`.
228
+
229
+ *Effects:* Direct-non-list-initializes *unex* with
230
+ `il, std::forward<Args>(args)...`.
231
+
232
+ *Ensures:* `has_value()` is `false`.
233
+
234
+ *Throws:* Any exception thrown by the initialization of *unex*.
235
+
236
+ #### Destructor <a id="expected.void.dtor">[[expected.void.dtor]]</a>
237
+
238
+ ``` cpp
239
+ constexpr ~expected();
240
+ ```
241
+
242
+ *Effects:* If `has_value()` is `false`, destroys *unex*.
243
+
244
+ *Remarks:* If `is_trivially_destructible_v<E>` is `true`, then this
245
+ destructor is a trivial destructor.
246
+
247
+ #### Assignment <a id="expected.void.assign">[[expected.void.assign]]</a>
248
+
249
+ ``` cpp
250
+ constexpr expected& operator=(const expected& rhs);
251
+ ```
252
+
253
+ *Effects:*
254
+
255
+ - If `this->has_value() && rhs.has_value()` is `true`, no effects.
256
+ - Otherwise, if `this->has_value()` is `true`, equivalent to:
257
+ `construct_at(addressof(`*`unex`*`), rhs.`*`unex`*`); `*`has_val`*` = false;`
258
+ - Otherwise, if `rhs.has_value()` is `true`, destroys *unex* and sets
259
+ *has_val* to `true`.
260
+ - Otherwise, equivalent to *`unex`*` = rhs.error()`.
261
+
262
+ *Returns:* `*this`.
263
+
264
+ *Remarks:* This operator is defined as deleted unless
265
+ `is_copy_assignable_v<E>` is `true` and `is_copy_constructible_v<E>` is
266
+ `true`.
267
+
268
+ ``` cpp
269
+ constexpr expected& operator=(expected&& rhs) noexcept(see below);
270
+ ```
271
+
272
+ *Effects:*
273
+
274
+ - If `this->has_value() && rhs.has_value()` is `true`, no effects.
275
+ - Otherwise, if `this->has_value()` is `true`, equivalent to:
276
+ ``` cpp
277
+ construct_at(addressof(unex), std::move(rhs.unex));
278
+ has_val = false;
279
+ ```
280
+ - Otherwise, if `rhs.has_value()` is `true`, destroys *unex* and sets
281
+ *has_val* to `true`.
282
+ - Otherwise, equivalent to *`unex`*` = std::move(rhs.error())`.
283
+
284
+ *Returns:* `*this`.
285
+
286
+ *Remarks:* The exception specification is equivalent to
287
+ `is_nothrow_move_constructible_v<E> && is_nothrow_move_assignable_v<E>`.
288
+
289
+ This operator is defined as deleted unless `is_move_constructible_v<E>`
290
+ is `true` and `is_move_assignable_v<E>` is `true`.
291
+
292
+ ``` cpp
293
+ template<class G>
294
+ constexpr expected& operator=(const unexpected<G>& e);
295
+ template<class G>
296
+ constexpr expected& operator=(unexpected<G>&& e);
297
+ ```
298
+
299
+ Let `GF` be `const G&` for the first overload and `G` for the second
300
+ overload.
301
+
302
+ *Constraints:* `is_constructible_v<E, GF>` is `true` and
303
+ `is_assignable_v<E&, GF>` is `true`.
304
+
305
+ *Effects:*
306
+
307
+ - If `has_value()` is `true`, equivalent to:
308
+ ``` cpp
309
+ construct_at(addressof(unex), std::forward<GF>(e.error()));
310
+ has_val = false;
311
+ ```
312
+ - Otherwise, equivalent to: *`unex`*` = std::forward<GF>(e.error());`
313
+
314
+ *Returns:* `*this`.
315
+
316
+ ``` cpp
317
+ constexpr void emplace() noexcept;
318
+ ```
319
+
320
+ *Effects:* If `has_value()` is `false`, destroys *unex* and sets
321
+ *has_val* to `true`.
322
+
323
+ #### Swap <a id="expected.void.swap">[[expected.void.swap]]</a>
324
+
325
+ ``` cpp
326
+ constexpr void swap(expected& rhs) noexcept(see below);
327
+ ```
328
+
329
+ *Constraints:* `is_swappable_v<E>` is `true` and
330
+ `is_move_constructible_v<E>` is `true`.
331
+
332
+ *Effects:* See [[expected.void.swap]].
333
+
334
+ **Table: `swap(expected&)` effects** <a id="expected.void.swap">[expected.void.swap]</a>
335
+
336
+ | \topline | `this->has_value()` | `!this->has_value()` |
337
+ | -------- | ------------------- | -------------------- |
338
+
339
+
340
+ For the case where `rhs.value()` is `false` and `this->has_value()` is
341
+ `true`, equivalent to:
342
+
343
+ ``` cpp
344
+ construct_at(addressof(unex), std::move(rhs.unex));
345
+ destroy_at(addressof(rhs.unex));
346
+ has_val = false;
347
+ rhs.has_val = true;
348
+ ```
349
+
350
+ *Throws:* Any exception thrown by the expressions in the *Effects*.
351
+
352
+ *Remarks:* The exception specification is equivalent to
353
+ `is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>`.
354
+
355
+ ``` cpp
356
+ friend constexpr void swap(expected& x, expected& y) noexcept(noexcept(x.swap(y)));
357
+ ```
358
+
359
+ *Effects:* Equivalent to `x.swap(y)`.
360
+
361
+ #### Observers <a id="expected.void.obs">[[expected.void.obs]]</a>
362
+
363
+ ``` cpp
364
+ constexpr explicit operator bool() const noexcept;
365
+ constexpr bool has_value() const noexcept;
366
+ ```
367
+
368
+ *Returns:* *has_val*.
369
+
370
+ ``` cpp
371
+ constexpr void operator*() const noexcept;
372
+ ```
373
+
374
+ *Preconditions:* `has_value()` is `true`.
375
+
376
+ ``` cpp
377
+ constexpr void value() const &;
378
+ ```
379
+
380
+ *Throws:* `bad_expected_access(error())` if `has_value()` is `false`.
381
+
382
+ ``` cpp
383
+ constexpr void value() &&;
384
+ ```
385
+
386
+ *Throws:* `bad_expected_access(std::move(error()))` if `has_value()` is
387
+ `false`.
388
+
389
+ ``` cpp
390
+ constexpr const E& error() const & noexcept;
391
+ constexpr E& error() & noexcept;
392
+ ```
393
+
394
+ *Preconditions:* `has_value()` is `false`.
395
+
396
+ *Returns:* *unex*.
397
+
398
+ ``` cpp
399
+ constexpr E&& error() && noexcept;
400
+ constexpr const E&& error() const && noexcept;
401
+ ```
402
+
403
+ *Preconditions:* `has_value()` is `false`.
404
+
405
+ *Returns:* `std::move(`*`unex`*`)`.
406
+
407
+ ``` cpp
408
+ template<class G = E> constexpr E error_or(G&& e) const &;
409
+ ```
410
+
411
+ *Mandates:* `is_copy_constructible_v<E>` is `true` and
412
+ `is_convertible_v<G, E>` is `true`.
413
+
414
+ *Returns:* `std::forward<G>(e)` if `has_value()` is `true`, `error()`
415
+ otherwise.
416
+
417
+ ``` cpp
418
+ template<class G = E> constexpr E error_or(G&& e) &&;
419
+ ```
420
+
421
+ *Mandates:* `is_move_constructible_v<E>` is `true` and
422
+ `is_convertible_v<G, E>` is `true`.
423
+
424
+ *Returns:* `std::forward<G>(e)` if `has_value()` is `true`,
425
+ `std::move(error())` otherwise.
426
+
427
+ #### Monadic operations <a id="expected.void.monadic">[[expected.void.monadic]]</a>
428
+
429
+ ``` cpp
430
+ template<class F> constexpr auto and_then(F&& f) &;
431
+ template<class F> constexpr auto and_then(F&& f) const &;
432
+ ```
433
+
434
+ Let `U` be `remove_cvref_t<invoke_result_t<F>>`.
435
+
436
+ *Constraints:* `is_constructible_v<E, decltype(error())>>` is `true`.
437
+
438
+ *Mandates:* `U` is a specialization of `expected` and
439
+ `is_same_v<U::error_type, E>` is `true`.
440
+
441
+ *Effects:* Equivalent to:
442
+
443
+ ``` cpp
444
+ if (has_value())
445
+ return invoke(std::forward<F>(f));
446
+ else
447
+ return U(unexpect, error());
448
+ ```
449
+
450
+ ``` cpp
451
+ template<class F> constexpr auto and_then(F&& f) &&;
452
+ template<class F> constexpr auto and_then(F&& f) const &&;
453
+ ```
454
+
455
+ Let `U` be `remove_cvref_t<invoke_result_t<F>>`.
456
+
457
+ *Constraints:* `is_constructible_v<E, decltype(std::move(error()))>` is
458
+ `true`.
459
+
460
+ *Mandates:* `U` is a specialization of `expected` and
461
+ `is_same_v<U::error_type, E>` is `true`.
462
+
463
+ *Effects:* Equivalent to:
464
+
465
+ ``` cpp
466
+ if (has_value())
467
+ return invoke(std::forward<F>(f));
468
+ else
469
+ return U(unexpect, std::move(error()));
470
+ ```
471
+
472
+ ``` cpp
473
+ template<class F> constexpr auto or_else(F&& f) &;
474
+ template<class F> constexpr auto or_else(F&& f) const &;
475
+ ```
476
+
477
+ Let `G` be `remove_cvref_t<invoke_result_t<F, decltype(error())>>`.
478
+
479
+ *Mandates:* `G` is a specialization of `expected` and
480
+ `is_same_v<G::value_type, T>` is `true`.
481
+
482
+ *Effects:* Equivalent to:
483
+
484
+ ``` cpp
485
+ if (has_value())
486
+ return G();
487
+ else
488
+ return invoke(std::forward<F>(f), error());
489
+ ```
490
+
491
+ ``` cpp
492
+ template<class F> constexpr auto or_else(F&& f) &&;
493
+ template<class F> constexpr auto or_else(F&& f) const &&;
494
+ ```
495
+
496
+ Let `G` be
497
+ `remove_cvref_t<invoke_result_t<F, decltype(std::move(error()))>>`.
498
+
499
+ *Mandates:* `G` is a specialization of `expected` and
500
+ `is_same_v<G::value_type, T>` is `true`.
501
+
502
+ *Effects:* Equivalent to:
503
+
504
+ ``` cpp
505
+ if (has_value())
506
+ return G();
507
+ else
508
+ return invoke(std::forward<F>(f), std::move(error()));
509
+ ```
510
+
511
+ ``` cpp
512
+ template<class F> constexpr auto transform(F&& f) &;
513
+ template<class F> constexpr auto transform(F&& f) const &;
514
+ ```
515
+
516
+ Let `U` be `remove_cv_t<invoke_result_t<F>>`.
517
+
518
+ *Constraints:* `is_constructible_v<E, decltype(error())>` is `true`.
519
+
520
+ *Mandates:* `U` is a valid value type for `expected`. If `is_void_v<U>`
521
+ is `false`, the declaration
522
+
523
+ ``` cpp
524
+ U u(invoke(std::forward<F>(f)));
525
+ ```
526
+
527
+ is well-formed.
528
+
529
+ *Effects:*
530
+
531
+ - If `has_value()` is `false`, returns
532
+ `expected<U, E>(unexpect, error())`.
533
+ - Otherwise, if `is_void_v<U>` is `false`, returns an `expected<U, E>`
534
+ object whose *has_val* member is `true` and *val* member is
535
+ direct-non-list-initialized with `invoke(std::forward<F>(f))`.
536
+ - Otherwise, evaluates `invoke(std::forward<F>(f))` and then returns
537
+ `expected<U, E>()`.
538
+
539
+ ``` cpp
540
+ template<class F> constexpr auto transform(F&& f) &&;
541
+ template<class F> constexpr auto transform(F&& f) const &&;
542
+ ```
543
+
544
+ Let `U` be `remove_cv_t<invoke_result_t<F>>`.
545
+
546
+ *Constraints:* `is_constructible_v<E, decltype(std::move(error()))>` is
547
+ `true`.
548
+
549
+ *Mandates:* `U` is a valid value type for `expected`. If `is_void_v<U>`
550
+ is `false`, the declaration
551
+
552
+ ``` cpp
553
+ U u(invoke(std::forward<F>(f)));
554
+ ```
555
+
556
+ is well-formed.
557
+
558
+ *Effects:*
559
+
560
+ - If `has_value()` is `false`, returns
561
+ `expected<U, E>(unexpect, std::move(error()))`.
562
+ - Otherwise, if `is_void_v<U>` is `false`, returns an `expected<U, E>`
563
+ object whose *has_val* member is `true` and *val* member is
564
+ direct-non-list-initialized with `invoke(std::forward<F>(f))`.
565
+ - Otherwise, evaluates `invoke(std::forward<F>(f))` and then returns
566
+ `expected<U, E>()`.
567
+
568
+ ``` cpp
569
+ template<class F> constexpr auto transform_error(F&& f) &;
570
+ template<class F> constexpr auto transform_error(F&& f) const &;
571
+ ```
572
+
573
+ Let `G` be `remove_cv_t<invoke_result_t<F, decltype(error())>>`.
574
+
575
+ *Mandates:* `G` is a valid template argument for `unexpected`
576
+ [[expected.un.general]] and the declaration
577
+
578
+ ``` cpp
579
+ G g(invoke(std::forward<F>(f), error()));
580
+ ```
581
+
582
+ is well-formed.
583
+
584
+ *Returns:* If `has_value()` is `true`, `expected<T, G>()`; otherwise, an
585
+ `expected<T, G>` object whose *has_val* member is `false` and *unex*
586
+ member is direct-non-list-initialized with
587
+ `invoke(std::forward<F>(f), error())`.
588
+
589
+ ``` cpp
590
+ template<class F> constexpr auto transform_error(F&& f) &&;
591
+ template<class F> constexpr auto transform_error(F&& f) const &&;
592
+ ```
593
+
594
+ Let `G` be
595
+ `remove_cv_t<invoke_result_t<F, decltype(std::move(error()))>>`.
596
+
597
+ *Mandates:* `G` is a valid template argument for `unexpected`
598
+ [[expected.un.general]] and the declaration
599
+
600
+ ``` cpp
601
+ G g(invoke(std::forward<F>(f), std::move(error())));
602
+ ```
603
+
604
+ is well-formed.
605
+
606
+ *Returns:* If `has_value()` is `true`, `expected<T, G>()`; otherwise, an
607
+ `expected<T, G>` object whose *has_val* member is `false` and *unex*
608
+ member is direct-non-list-initialized with
609
+ `invoke(std::forward<F>(f), std::move(error()))`.
610
+
611
+ #### Equality operators <a id="expected.void.eq">[[expected.void.eq]]</a>
612
+
613
+ ``` cpp
614
+ template<class T2, class E2> requires is_void_v<T2>
615
+ friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);
616
+ ```
617
+
618
+ *Mandates:* The expression `x.error() == y.error()` is well-formed and
619
+ its result is convertible to `bool`.
620
+
621
+ *Returns:* If `x.has_value()` does not equal `y.has_value()`, `false`;
622
+ otherwise `x.has_value() || static_cast<bool>(x.error() == y.error())`.
623
+
624
+ ``` cpp
625
+ template<class E2>
626
+ friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);
627
+ ```
628
+
629
+ *Mandates:* The expression `x.error() == e.error()` is well-formed and
630
+ its result is convertible to `bool`.
631
+
632
+ *Returns:*
633
+ `!x.has_value() && static_cast<bool>(x.error() == e.error())`.
634
+