MySQL 9.1.0
Source Code Documentation
expected.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2019, 2024, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef MYSQL_HARNESS_STDX_EXPECTED_H_
27#define MYSQL_HARNESS_STDX_EXPECTED_H_
28
29// implementation of C++23's std::expected<> in C++20
30//
31// and http://wg21.link/p2505 (r0) for .and_then(), .or_else() and .transform()
32//
33// See http://wg21.link/p0323
34
35#include <cassert>
36#include <functional> // invoke
37#include <initializer_list>
38#include <memory> // construct_at, destroy_at
39#include <type_traits>
40#include <utility> // std::forward
41
42#include "my_compiler.h"
43
44#if defined(__cpp_concepts)
45#if __cpp_concepts >= 202002L
46#define CXX_HAS_CONDITIONAL_TRIVIAL_DESTRUCTOR
47#elif defined(__clang_major__)
48#if __clang_major__ >= 15
49// clang added partial support for overloading destructors (P0848) in clang-15
50// ... but didn't bump the concepts version yet.
51#define CXX_HAS_CONDITIONAL_TRIVIAL_DESTRUCTOR
52#endif
53#elif defined(__GNUC_MAJOR__)
54#if __GNUC_MAJOR__ >= 10
55// gcc added partial support for overloading destructors (P0848) in gcc-10
56// ... but didn't bump the concepts version yet.
57#define CXX_HAS_CONDITIONAL_TRIVIAL_DESTRUCTOR
58#endif
59#else // msvc
60#define CXX_HAS_CONDITIONAL_TRIVIAL_DESTRUCTOR
61#endif
62#endif
63
64namespace stdx {
65
66#ifndef IN_DOXYGEN
67// doxygen gets confused by the inheritence structure of bad_expected_access.
68
69template <class E>
70class bad_expected_access;
71
72template <>
73class bad_expected_access<void> : public std::exception {
74 protected:
75 bad_expected_access() {}
76 bad_expected_access(const bad_expected_access &) = default;
77 bad_expected_access(bad_expected_access &&) = default;
78
79 bad_expected_access &operator=(const bad_expected_access &) = default;
80 bad_expected_access &operator=(bad_expected_access &&) = default;
81
82 ~bad_expected_access() override = default;
83
84 public:
85 const char *what() const noexcept override { return "bad expected access"; }
86};
87
88template <class E>
89class bad_expected_access : public bad_expected_access<void> {
90 public:
91 explicit bad_expected_access(E e) : e_(std::move(e)) {}
92
93 // error accessors
94 const E &error() const &noexcept { return e_; }
95 const E &&error() const &&noexcept { return e_; }
96 E &error() &noexcept { return e_; }
97 E &&error() &&noexcept { return e_; }
98
99 private:
100 E e_;
101};
102#endif
103
104// inplace construction of unexpected values.
106 explicit unexpect_t() = default;
107};
108
109inline constexpr unexpect_t unexpect{};
110
111template <typename E>
113 public:
114 static_assert(!std::is_same<E, void>::value, "E must not be void");
115
116 using error_type = E;
117
118 // constructor
119
120 constexpr unexpected(const unexpected &) = default;
121 constexpr unexpected(unexpected &&) noexcept = default;
122
123 template <class Err = E>
124 constexpr explicit unexpected(Err &&err) //
125 noexcept(std::is_nothrow_constructible_v<E, Err>)
126 requires(!std::is_same_v<std::remove_cvref_t<Err>, unexpected> &&
127 !std::is_same_v<std::remove_cvref_t<Err>, std::in_place_t> &&
128 std::is_constructible_v<E, Err>) //
129 : error_(std::forward<Err>(err)) {}
130
131 template <class... Args>
132 constexpr explicit unexpected(std::in_place_t, Args &&...args) //
133 noexcept(std::is_nothrow_constructible_v<E, Args...>)
134 requires std::constructible_from<E, Args &&...>
135 : error_(std::forward<Args>(args)...) {}
136
137 template <class U, class... Args>
138 constexpr explicit unexpected(std::in_place_t, std::initializer_list<U> il,
139 Args &&...args) //
140 noexcept(std::is_nothrow_constructible_v<E, std::initializer_list<U> &,
141 Args...>)
142 requires(std::constructible_from<E, std::initializer_list<U>,
143 Args && ...>) //
144 : error_(il, std::forward<Args>(args)...) {}
145
146 // assignment
147
148 constexpr unexpected &operator=(const unexpected &) = default;
149 constexpr unexpected &operator=(unexpected &&) noexcept = default;
150
151 // value access
152
153 constexpr error_type &error() &noexcept { return error_; }
154 constexpr const error_type &error() const &noexcept { return error_; }
155 constexpr error_type &&error() &&noexcept { return std::move(error_); }
156 constexpr const error_type &&error() const &&noexcept {
157 return std::move(error_);
158 }
159
160 // swap
161
162 constexpr void swap(unexpected &other) //
163 noexcept(std::is_nothrow_swappable_v<E>)
164 requires(std::is_swappable_v<E>)
165 {
166 using std::swap;
167
168 swap(error_, other.error_);
169 }
170
171 // comparison
172
173 template <class E2>
174 friend constexpr bool operator==(const unexpected &lhs,
175 const stdx::unexpected<E2> &rhs) {
176 return lhs.error() == rhs.error();
177 }
178
179 friend constexpr void swap(unexpected &lhs, unexpected &rhs) noexcept(
180 noexcept(lhs.swap(rhs))) {
181 lhs.swap(rhs);
182 }
183
184 private:
186};
187
188// deduction guide
189template <class E>
191
192template <class T, class E>
193class expected;
194
195namespace impl {
196
197template <class T>
198constexpr bool is_expected = false;
199
200template <class T, class E>
201constexpr bool is_expected<expected<T, E>> = true;
202
203template <class T>
204constexpr bool is_unexpected = false;
205
206template <class T>
207constexpr bool is_unexpected<unexpected<T>> = true;
208
209template <class NewT, class OldT, class... Args>
210constexpr void reinit_expected(NewT *new_val, OldT *old_val, Args &&...args) {
211 if constexpr (std::is_nothrow_constructible_v<NewT, Args...>) {
212 std::destroy_at(old_val);
213 std::construct_at(new_val, std::forward<Args>(args)...);
214 } else if constexpr (std::is_nothrow_move_constructible_v<NewT>) {
215 NewT tmp(std::forward<Args>(args)...);
216
217 std::destroy_at(old_val);
218 std::construct_at(new_val, std::move(tmp));
219 } else {
220 OldT tmp(std::move(*old_val));
221
222 std::destroy_at(old_val);
223 try {
224 std::construct_at(new_val, std::forward<Args>(args)...);
225 } catch (...) {
226 std::construct_at(old_val, std::move(tmp));
227 throw;
228 }
229 }
230}
231
232} // namespace impl
233
234namespace base {
235
236template <class Exp, class Func,
237 typename value_type = typename std::decay_t<Exp>::value_type>
238 requires(std::is_void_v<value_type>
239 ? std::is_invocable_v<Func>
240 : std::is_invocable_v<Func, value_type>) //
241constexpr auto and_then_impl(Exp &&exp, Func &&func) {
242 if constexpr (std::is_void_v<value_type>) {
243 using Ret = std::invoke_result_t<Func>;
244
245 static_assert(stdx::impl::is_expected<Ret>,
246 "Func must return a stdx::expected<>");
247
248 if (exp.has_value()) {
249 return std::invoke(func);
250 } else {
251 return Ret{stdx::unexpect, std::forward<Exp>(exp).error()};
252 }
253 } else {
254 using Ret = std::invoke_result_t<Func, value_type>;
255
256 static_assert(stdx::impl::is_expected<Ret>,
257 "Func must return a stdx::expected<>");
258
259 if (exp.has_value()) {
260 return std::invoke(func, *std::forward<Exp>(exp));
261 } else {
262 return Ret{stdx::unexpect, std::forward<Exp>(exp).error()};
263 }
264 }
265}
266
267template <class Exp, class Func,
268 typename error_type = typename std::decay_t<Exp>::error_type>
269 requires std::is_invocable_v<Func, error_type>
270constexpr auto or_else_impl(Exp &&exp, Func &&func) {
271 static_assert(
272 std::is_same_v<
273 std::remove_cvref_t<std::invoke_result_t<Func, error_type>>, Exp>,
274 "Func must return an expected<>");
275
276 if (exp.has_value()) {
277 return std::forward<Exp>(exp);
278 }
279
280 return std::invoke(std::forward<Func>(func), std::forward<Exp>(exp).error());
281}
282
283} // namespace base
284
285template <class T, class E>
286class expected {
287 public:
288 static_assert(!std::is_void_v<E>, "E must not be void");
289 static_assert(!std::is_reference_v<T>, "T must not be a reference");
290 static_assert(!std::is_function_v<T>, "T must not be a function");
291 static_assert(!std::is_same_v<std::remove_cv_t<T>, std::in_place_t>,
292 "T must not be std::in_place_t");
293 static_assert(!std::is_same_v<std::remove_cv_t<T>, unexpect_t>,
294 "T must not be stdx::unexpect_t");
295 static_assert(!std::is_same_v<T, std::remove_cv<unexpected<E>>>,
296 "T must not be unexpected<E>");
297
298 using value_type = T;
299 using error_type = E;
301
302 template <typename U>
304
305 // (1)
306 constexpr expected() //
307 noexcept(std::is_nothrow_default_constructible_v<T>)
308 requires std::is_default_constructible_v<T>
309 : val_{}, has_value_(true) {}
310
311 // (2)
312 constexpr expected(const expected &other) = default;
313
314 constexpr expected(const expected &other) //
315 noexcept((std::is_nothrow_copy_constructible_v<T> &&
316 std::is_nothrow_copy_constructible_v<E>))
317 requires((std::is_copy_constructible_v<T> &&
318 std::is_copy_constructible_v<E> &&
319 (!std::is_trivially_copy_constructible_v<T> ||
320 !std::is_trivially_copy_constructible_v<E>)))
321 : has_value_{other.has_value()} {
322 if (has_value()) {
323 std::construct_at(std::addressof(val_), other.val_);
324 } else {
325 std::construct_at(std::addressof(unex_), other.unex_);
326 }
327 }
328
329 // (3)
330 constexpr expected(expected &&other) = default;
331
332 constexpr expected(expected &&other) //
333 noexcept((std::is_nothrow_move_constructible_v<E> &&
334 std::is_nothrow_move_constructible_v<T>))
335 requires((std::is_move_constructible_v<T> &&
336 std::is_move_constructible_v<E> &&
337 (!std::is_trivially_move_constructible_v<T> ||
338 !std::is_trivially_move_constructible_v<E>))) //
339 : has_value_{other.has_value()} {
340 if (has_value()) {
341 std::construct_at(std::addressof(val_), std::move(other.val_));
342 } else {
343 std::construct_at(std::addressof(unex_), std::move(other.unex_));
344 }
345 }
346
347 template <class UF, class GF>
348 static constexpr bool constructor_is_explicit =
349 !std::is_convertible_v<UF, T> || !std::is_convertible_v<GF, E>;
350
351 //
352 template <class U, class G, class UF, class GF>
353 static constexpr bool can_value_convert_construct =
354 (std::is_constructible_v<T, UF> && //
355 std::is_constructible_v<E, GF> &&
356 !std::is_constructible_v<T, expected<U, G> &> &&
357 !std::is_constructible_v<T, expected<U, G>> &&
358 !std::is_constructible_v<T, const expected<U, G> &> &&
359 !std::is_constructible_v<T, const expected<U, G>> &&
360 !std::is_convertible_v<expected<U, G> &, T> &&
361 !std::is_convertible_v<expected<U, G>, T> &&
362 !std::is_convertible_v<const expected<U, G> &, T> &&
363 !std::is_convertible_v<const expected<U, G>, T> &&
364 !std::is_constructible_v<unexpected<E>, expected<U, G> &> &&
365 !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
366 !std::is_constructible_v<unexpected<E>, const expected<U, G> &> &&
367 !std::is_constructible_v<unexpected<E>, const expected<U, G>>);
368
369 // (4)
370 template <class U, class G, class UF = std::add_lvalue_reference_t<const U>,
371 class GF = const G &>
372 constexpr explicit(constructor_is_explicit<UF, GF>)
374 requires can_value_convert_construct<U, G, UF, GF>
375 : has_value_{rhs.has_value()} {
376 if (rhs.has_value()) {
377 std::construct_at(std::addressof(val_), std::forward<UF>(*rhs));
378 } else {
379 std::construct_at(std::addressof(unex_), std::forward<GF>(rhs.error()));
380 }
381 }
382
383 // (5)
384 template <class U, class G, class UF = U, class GF = G>
385 constexpr explicit(constructor_is_explicit<UF, GF>)
387 requires can_value_convert_construct<U, G, UF, GF>
388 : has_value_{rhs.has_value()} {
389 if (rhs.has_value()) {
390 std::construct_at(std::addressof(val_), std::forward<UF>(*rhs));
391 } else {
392 std::construct_at(std::addressof(unex_), std::forward<GF>(rhs.error()));
393 }
394 }
395
396 template <class U>
397 static constexpr bool can_construct_from_value_type =
398 !std::is_same_v<std::in_place_t, std::remove_cvref_t<U>> &&
399 !std::is_same_v<expected, std::remove_cvref_t<U>> &&
400 std::is_constructible_v<T, U> &&
401 !impl::is_unexpected<std::remove_cvref_t<U>> &&
402 !impl::is_expected<std::remove_cvref_t<T>>;
403
404 // (6)
405 template <class U = T>
406 constexpr explicit(!std::is_convertible_v<U, T>) expected(U &&val)
407 requires can_construct_from_value_type<U>
408 : val_(std::forward<U>(val)), has_value_{true} {}
409
410 // (7)
411 template <class G>
412 constexpr explicit(!std::is_convertible_v<const G &, E>)
414 requires std::is_constructible_v<E, const G &>
415 : unex_(err.error()), has_value_{false} {}
416
417 // (8)
418 template <class G>
419 constexpr explicit(!std::is_convertible_v<G, E>) expected(unexpected<G> &&err)
420 requires std::is_constructible_v<E, G>
421 : unex_(std::move(err.error())), has_value_{false} {}
422
423 // (9)
424 template <class... Args>
425 constexpr explicit expected(std::in_place_t, Args &&...args)
426 requires std::is_constructible_v<T, Args...>
427 : val_(std::forward<Args>(args)...), has_value_{true} {}
428
429 // (10)
430 template <class U, class... Args>
431 constexpr explicit expected(std::in_place_t, std::initializer_list<U> il,
432 Args &&...args)
433 requires std::is_constructible_v<T, std::initializer_list<U> &, Args...>
434 : val_(il, std::forward<Args>(args)...), has_value_{true} {}
435
436 // (11) skipped, only for T-is-void
437
438 // (12)
439 template <class... Args>
440 constexpr explicit expected(stdx::unexpect_t, Args &&...args)
441 requires std::is_constructible_v<E, Args &&...>
442 : unex_(std::forward<Args>(args)...), has_value_{false} {}
443
444 // (13)
445 template <class U, class... Args>
446 constexpr explicit expected(stdx::unexpect_t, std::initializer_list<U> il,
447 Args &&...args)
448 requires std::is_constructible_v<E, std::initializer_list<U> &, Args...>
449 : unex_(il, std::forward<Args>(args)...), has_value_{false} {}
450
451 // assignment
452
453 // (1)
454 constexpr expected &operator=(expected const &other)
455 requires((std::is_copy_assignable_v<T> && //
456 std::is_copy_constructible_v<T> && //
457 std::is_copy_assignable_v<E> && //
458 std::is_copy_constructible_v<E> && //
459 (std::is_nothrow_move_constructible_v<T> ||
460 std::is_nothrow_move_constructible_v<E>)))
461 {
462 if (other.has_value()) {
463 assign_val(other.val_);
464 } else {
465 assign_unex(other.unex_);
466 }
467
468 return *this;
469 }
470
471 // (2)
472 constexpr expected &operator=(expected &&other)
473 requires((std::is_move_assignable_v<T> && //
474 std::is_move_constructible_v<T> && //
475 std::is_move_assignable_v<E> && //
476 std::is_move_constructible_v<E> && //
477 (std::is_nothrow_move_constructible_v<T> ||
478 std::is_nothrow_move_constructible_v<E>)))
479 {
480 if (other.has_value()) {
481 assign_val(std::move(other.val_));
482 } else {
483 assign_unex(std::move(other.unex_));
484 }
485
486 return *this;
487 }
488
489 // (3) assign from expected value
490 template <class U = T>
491 constexpr expected &operator=(U &&val)
492 requires((!std::is_same_v<expected<T, E>, std::remove_cvref_t<U>> && //
493 !impl::is_unexpected<std::remove_cvref_t<U>> && //
494 std::is_constructible_v<T, U> && //
495 std::is_assignable_v<T &, U> && //
496 (std::is_nothrow_constructible_v<T, U> || //
497 std::is_nothrow_move_constructible_v<T> || //
498 std::is_nothrow_move_constructible_v<E>)))
499 {
500 assign_val(std::forward<U>(val));
501
502 return *this;
503 }
504
505 // (4)
506 template <class G, class GF = const G &>
507 constexpr expected &operator=(const unexpected<G> &other)
508 requires((std::is_constructible_v<E, GF> && //
509 std::is_assignable_v<E &, GF> && //
510 (std::is_nothrow_constructible_v<E, GF> || //
511 std::is_nothrow_move_constructible_v<T> || //
512 std::is_nothrow_move_constructible_v<E>)))
513 {
514 assign_unex(other.error());
515
516 return *this;
517 }
518
519 // (5)
520 template <class G, class GF = G>
521 constexpr expected &operator=(unexpected<G> &&other)
522 requires((std::is_constructible_v<E, GF> && //
523 std::is_assignable_v<E &, GF> && //
524 (std::is_nothrow_constructible_v<E, GF> || //
525 std::is_nothrow_move_constructible_v<T> || //
526 std::is_nothrow_move_constructible_v<E>)))
527 {
528 assign_unex(std::move(other.error()));
529
530 return *this;
531 }
532
533 // destruct
534#if defined(CXX_HAS_CONDITIONAL_TRIVIAL_DESTRUCTOR)
535 constexpr ~expected()
536 requires((std::is_trivially_destructible_v<T> &&
537 std::is_trivially_destructible_v<E>))
538 = default;
539#endif
540
541 constexpr ~expected() {
542 if (has_value()) {
543 std::destroy_at(std::addressof(val_));
544 } else {
545 std::destroy_at(std::addressof(unex_));
546 }
547 }
548
549 // emplace
550 template <class... Args>
551 constexpr T &emplace(Args &&...args) noexcept
552 requires(std::is_nothrow_constructible_v<T, Args...>)
553 {
554 if (has_value()) {
555 std::destroy_at(std::addressof(val_));
556 } else {
557 std::destroy_at(std::addressof(unex_));
558 has_value_ = true;
559 }
560
561 return *std::construct_at(std::addressof(val_),
562 std::forward<Args>(args)...);
563 }
564
565 template <class U, class... Args>
566 constexpr T &emplace(std::initializer_list<U> il, Args &&...args) noexcept
567 requires(
568 std::is_nothrow_constructible_v<T, std::initializer_list<U> &, Args...>)
569 {
570 if (has_value()) {
571 std::destroy_at(std::addressof(val_));
572 } else {
573 std::destroy_at(std::addressof(unex_));
574 has_value_ = true;
575 }
576
577 return *std::construct_at(std::addressof(val_), il,
578 std::forward<Args>(args)...);
579 }
580
581 // swap
582 constexpr void swap(expected &other) //
583 noexcept((std::is_nothrow_move_constructible_v<T> && //
584 std::is_nothrow_move_constructible_v<E> && //
585 std::is_nothrow_swappable_v<T> && //
586 std::is_nothrow_swappable_v<E>))
587 requires((std::is_swappable_v<T> && //
588 std::is_swappable_v<E> && //
589 std::is_move_constructible_v<T> && //
590 std::is_move_constructible_v<E> && //
591 (std::is_nothrow_move_constructible_v<T> || //
592 std::is_nothrow_move_constructible_v<E>)))
593 {
594 using std::swap;
595
596 if (bool(*this) && bool(other)) {
597 swap(val_, other.val_);
598 } else if (!bool(*this) && !bool(other)) {
599 swap(unex_, other.unex_);
600 } else if (bool(*this) && !bool(other)) {
601 if constexpr (std::is_nothrow_move_constructible_v<E>) {
602 error_type tmp(std::move(other.error()));
603
604 std::destroy_at(std::addressof(other.unex_));
605 try {
606 std::construct_at(std::addressof(other.val_), std::move(val_));
607 std::destroy_at(std::addressof(val_));
608 std::construct_at(std::addressof(unex_), std::move(tmp));
609 } catch (...) {
610 // restore old value.
611 std::construct_at(std::addressof(other.unex_), std::move(tmp));
612 throw;
613 }
614 } else {
615 value_type tmp(std::move(val_));
616
617 std::destroy_at(std::addressof(val_));
618 try {
619 std::construct_at(std::addressof(unex_), std::move(other.unex_));
620 std::destroy_at(std::addressof(other.unex_));
621 std::construct_at(std::addressof(val_), std::move(tmp));
622 } catch (...) {
623 // restore old value.
624 std::construct_at(std::addressof(val_), std::move(tmp));
625 throw;
626 }
627 }
628
629 has_value_ = false;
630 other.has_value_ = true;
631 } else if (!bool(*this) && bool(other)) {
632 other.swap(*this);
633 }
634 }
635
636 constexpr bool has_value() const { return has_value_; }
637 constexpr explicit operator bool() const noexcept { return has_value(); }
638
639 // value accessors
640
641 // the macro only exists for clang-format-10 to not get the formatting wrong.
642#define LIKELY(x) (x) [[likely]]
643
644 // (1)
645 constexpr value_type &value() & {
646 static_assert(std::is_copy_constructible_v<E>,
647 "error-type must be copy-constructible");
648 if LIKELY (has_value()) {
649 return val_;
650 }
651
652 throw bad_expected_access(std::as_const(error()));
653 }
654
655 // (2)
656 constexpr const value_type &value() const & {
657 static_assert(std::is_copy_constructible_v<E>,
658 "error-type must be copy-constructible");
659
660 if LIKELY (has_value()) {
661 return val_;
662 }
663
664 throw bad_expected_access(std::as_const(error()));
665 }
666
667 // (3)
668 constexpr value_type &&value() && {
669 static_assert(std::is_copy_constructible_v<E> &&
670 std::is_constructible_v<E, decltype(std::move(error()))>);
671
672 if LIKELY (has_value()) {
673 return std::move(val_);
674 }
675
676 throw bad_expected_access(std::move(error()));
677 }
678
679 // (4)
680 constexpr const value_type &&value() const && {
681 static_assert(std::is_copy_constructible_v<E> &&
682 std::is_constructible_v<E, decltype(std::move(error()))>);
683
684 if LIKELY (has_value()) {
685 return std::move(val_);
686 }
687
688 throw bad_expected_access(std::move(error()));
689 }
690
691#undef LIKELY
692
693 // unchecked value access
694
695 // (1)
696 constexpr const value_type *operator->() const noexcept {
697 assert(has_value());
698
699 return std::addressof(val_);
700 }
701
702 // (2)
703 constexpr value_type *operator->() noexcept {
704 assert(has_value());
705
706 return std::addressof(val_);
707 }
708
709 // (3)
710 constexpr const value_type &operator*() const &noexcept {
711 assert(has_value());
712
713 return val_;
714 }
715
716 // (4)
717 constexpr value_type &operator*() &noexcept {
718 assert(has_value());
719
720 return val_;
721 }
722
723 // (5)
724 constexpr const value_type &&operator*() const &&noexcept {
725 assert(has_value());
726
727 return std::move(val_);
728 }
729
730 // (6)
731 constexpr value_type &&operator*() &&noexcept {
732 assert(has_value());
733
734 return std::move(val_);
735 }
736
737 // value_or
738
739 // (1)
740 template <class U>
741 constexpr value_type value_or(U &&v) const & {
742 static_assert(
743 std::is_copy_constructible_v<T> && std::is_convertible_v<U &&, T>,
744 "T must be copy-constructible and convertible from U&&");
745
746 return has_value() ? **this : static_cast<T>(std::forward<U>(v));
747 }
748
749 // (2)
750 template <class U>
751 constexpr value_type value_or(U &&v) && {
752 static_assert(
753 std::is_move_constructible_v<T> && std::is_convertible_v<U &&, T>,
754 "T must be move-constructible and convertible from U&&");
755
756 return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v));
757 }
758
759 // error accessors
760 constexpr const error_type &error() const & { return unex_; }
761 constexpr const error_type &&error() const && { return std::move(unex_); }
762 constexpr error_type &error() & { return unex_; }
763 constexpr error_type &&error() && { return std::move(unex_); }
764
765 // operator==
766
767 // (1)
768 template <class T2, class E2>
769 requires(!std::is_void_v<T2>)
770 friend constexpr bool operator==(const expected &lhs,
772 if (lhs.has_value() != rhs.has_value()) return false;
773
774 if (!lhs.has_value()) return lhs.error() == rhs.error();
775 return static_cast<bool>(*lhs == *rhs);
776 }
777
778 // (3)
779 template <class T2>
780 requires(!impl::is_expected<T2>)
781 friend constexpr bool operator==(const expected &lhs, const T2 &rhs) {
782 return lhs.has_value() && static_cast<bool>(*lhs == rhs);
783 }
784
785 // (4)
786 template <class E2>
787 friend constexpr bool operator==(const expected &lhs,
788 const unexpected<E2> &rhs) {
789 if (lhs.has_value()) return false;
790
791 return static_cast<bool>(lhs.error() == rhs.error());
792 }
793
794 //
795 // and_then
796 //
797
798 template <class Func>
799 constexpr auto and_then(Func &&func) & {
800 return base::and_then_impl(*this, std::forward<Func>(func));
801 }
802
803 template <class Func>
804 constexpr auto and_then(Func &&func) && {
805 return base::and_then_impl(std::move(*this), std::forward<Func>(func));
806 }
807
808 template <class Func>
809 constexpr auto and_then(Func &&func) const & {
810 return base::and_then_impl(*this, std::forward<Func>(func));
811 }
812
813 template <class Func>
814 constexpr auto and_then(Func &&func) const && {
815 return base::and_then_impl(std::move(*this), std::forward<Func>(func));
816 }
817
818 //
819 // or_else
820 //
821
822 template <class Func>
823 constexpr auto or_else(Func &&func) & {
824 return base::or_else_impl(*this, std::forward<Func>(func));
825 }
826
827 template <class Func>
828 constexpr auto or_else(Func &&func) && {
829 return base::or_else_impl(std::move(*this), std::forward<Func>(func));
830 }
831
832 template <class Func>
833 constexpr auto or_else(Func &&func) const & {
834 return base::or_else_impl(*this, std::forward<Func>(func));
835 }
836
837 template <class Func>
838 constexpr auto or_else(Func &&func) const && {
839 return base::or_else_impl(std::move(*this), std::forward<Func>(func));
840 }
841
842 //
843 // transform
844 //
845
846 template <class Func>
847 constexpr auto transform(Func &&func) & {
848 return expected_transform_impl(*this, std::forward<Func>(func));
849 }
850
851 template <class Func>
852 constexpr auto transform(Func &&func) && {
853 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
854 }
855
856 template <class Func>
857 constexpr auto transform(Func &&func) const & {
858 return expected_transform_impl(*this, std::forward<Func>(func));
859 }
860
861 template <class Func>
862 constexpr auto transform(Func &&func) const && {
863 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
864 }
865
866 private:
867 template <class U>
868 void assign_val(U &&u) {
869 if (has_value_) {
870 val_ = std::forward<U>(u);
871 } else {
872 impl::reinit_expected(std::addressof(val_), std::addressof(unex_),
873 std::forward<U>(u));
874 has_value_ = true;
875 }
876 }
877
878 template <class U>
879 void assign_unex(U &&u) {
880 if (has_value_) {
881 impl::reinit_expected(std::addressof(unex_), std::addressof(val_),
882 std::forward<U>(u));
883 has_value_ = false;
884 } else {
885 unex_ = std::forward<U>(u);
886 }
887 }
888
889 union {
892#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 12
893 // workaround GCC 10/11's "maybe-uninitialized"
894 // GCC 12 and 13 do not report it.
895 volatile char gcc_pr80635_workaround_maybe_uninitialized_;
896#endif
897 };
898
900};
901
902template <class T, class E>
903 requires(std::is_void_v<T>)
905 public:
906 static_assert(!std::is_void_v<E>, "E must not be void");
907 static_assert(!std::is_reference_v<T>, "T must not be a reference");
908 static_assert(!std::is_same_v<T, std::remove_cv<std::in_place_t>>,
909 "T must not be std::in_place_t");
910 static_assert(!std::is_same_v<T, std::remove_cv<unexpected<E>>>,
911 "T must not be unexpected<E>");
912 static_assert(!std::is_reference_v<E>, "E must not be a reference");
913
914 using value_type = T;
915 using error_type = E;
917
918 // (1)
919 constexpr expected() noexcept : dummy_(), has_value_(true) {}
920
921 // (2)
922 constexpr expected(const expected &other) = default;
923
924 constexpr expected(const expected &other)
925 requires((std::is_copy_constructible_v<E> &&
926 !std::is_trivially_copy_constructible_v<E>))
927 : dummy_(), has_value_{other.has_value()} {
928 if (!has_value()) {
929 std::construct_at(std::addressof(unex_), other.unex_);
930 }
931 }
932
933 // (3)
934 constexpr expected(expected &&other) = default;
935
936 constexpr expected(expected &&other) //
937 noexcept((std::is_nothrow_move_constructible_v<T>))
938 requires((std::is_move_constructible_v<E> &&
939 !std::is_trivially_move_constructible_v<E>))
940 : dummy_(), has_value_{other.has_value()} {
941 if (!has_value()) {
942 std::construct_at(std::addressof(unex_), std::move(other.unex_));
943 }
944 }
945
946 template <class UF, class GF>
947 static constexpr bool constructor_is_explicit =
948 (!std::is_convertible_v<UF, T> || !std::is_convertible_v<GF, E>);
949
950 template <class U, class G, class UF, class GF>
951 static constexpr bool can_value_convert_construct =
952 (std::is_void_v<U> && std::is_constructible_v<E, GF> &&
953 !std::is_constructible_v<unexpected<E>, expected<U, G> &> &&
954 !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
955 !std::is_constructible_v<unexpected<E>, const expected<U, G> &> &&
956 !std::is_constructible_v<unexpected<E>, const expected<U, G>>);
957
958 // (4)
959 template <class U, class G, class UF = std::add_lvalue_reference_t<const U>,
960 class GF = const G &>
961 constexpr explicit(constructor_is_explicit<UF, GF>)
963 requires can_value_convert_construct<U, G, UF, GF>
964 : dummy_(), has_value_{rhs.has_value()} {
965 if (!rhs.has_value()) {
966 std::construct_at(std::addressof(unex_), rhs.error());
967 }
968 }
969
970 // (5)
971 template <class U, class G, class UF = U, class GF = G>
972 constexpr explicit(constructor_is_explicit<UF, GF>) //
973 expected(expected<U, G> &&rhs) //
974 requires can_value_convert_construct<U, G, UF, GF>
975 : dummy_(), has_value_{rhs.has_value()} {
976 if (!rhs.has_value()) {
977 std::construct_at(std::addressof(unex_), std::move(rhs.error()));
978 }
979 }
980
981 // (6) requires T is not cv void.
982
983 // (7)
984 template <class G>
985 constexpr explicit(!std::is_convertible_v<const G &, E>)
986 expected(const unexpected<G> &err)
987 requires std::is_constructible_v<E, const G &>
988 : unex_(err.error()), has_value_{false} {}
989
990 // (8)
991 template <class G>
992 constexpr explicit(!std::is_convertible_v<G, E>) //
993 expected(unexpected<G> &&err)
994 requires std::is_constructible_v<E, G>
995 : unex_(std::move(err.error())), has_value_{false} {}
996
997 // (9) requires T is not cv void.
998
999 // (10) requires T is not cv void.
1000
1001 // (11)
1002 template <class... Args>
1003 constexpr explicit expected(std::in_place_t) : has_value_{true} {}
1004
1005 // (12)
1006 template <class... Args>
1007 constexpr explicit expected(stdx::unexpect_t, Args &&...args)
1008 requires std::is_constructible_v<E, Args...>
1009 : unex_(std::forward<Args>(args)...), has_value_{false} {}
1010
1011 // (13)
1012 template <class U, class... Args>
1013 constexpr explicit expected(stdx::unexpect_t, std::initializer_list<U> il,
1014 Args &&...args) //
1015 requires std::is_constructible_v<E, std::initializer_list<U> &, Args...>
1016 : unex_(il, std::forward<Args>(args)...), has_value_{false} {}
1017
1018 // assignment
1019
1020 // (1)
1021 constexpr expected &operator=(expected const &other)
1022 requires((std::is_copy_assignable_v<E> && //
1023 std::is_copy_constructible_v<E>))
1024 {
1025 if (other.has_value()) {
1026 emplace(); // destroys unex_ and sets has_value_ = true
1027 } else {
1028 assign_unex(other.unex_);
1029 }
1030
1031 return *this;
1032 }
1033
1034 // (2)
1035 constexpr expected &operator=(expected &&other)
1036 requires((std::is_move_assignable_v<E> && //
1037 std::is_move_constructible_v<E>))
1038 {
1039 if (other.has_value()) {
1040 emplace();
1041 } else {
1042 assign_unex(other.unex_);
1043 }
1044 return *this;
1045 }
1046
1047 // (3) requires T is not cv void.
1048
1049 // (4)
1050 template <class G, class GF = const G &>
1051 constexpr expected &operator=(const unexpected<G> &other)
1052 requires((std::is_constructible_v<E, GF> && //
1053 std::is_assignable_v<E &, GF>))
1054 {
1055 assign_unex(other.error());
1056
1057 return *this;
1058 }
1059
1060 // (5)
1061 template <class G, class GF = G>
1062 constexpr expected &operator=(unexpected<G> &&other)
1063 requires(std::is_constructible_v<E, GF> && //
1064 std::is_assignable_v<E &, GF>)
1065 {
1066 assign_unex(std::move(other.error()));
1067
1068 return *this;
1069 }
1070
1071 // destruct
1072#if defined(CXX_HAS_CONDITIONAL_TRIVIAL_DESTRUCTOR)
1073 constexpr ~expected()
1074 requires((std::is_trivially_destructible_v<E>))
1075 = default;
1076#endif
1077
1078 constexpr ~expected() {
1079 if (!has_value()) {
1080 std::destroy_at(std::addressof(unex_));
1081 }
1082 }
1083
1084 // emplace
1085 constexpr void emplace() noexcept {
1086 if (!has_value()) {
1087 std::destroy_at(std::addressof(unex_));
1088 has_value_ = true;
1089 }
1090 }
1091
1092 // swap
1093 constexpr void swap(expected &other) //
1094 noexcept((std::is_nothrow_move_constructible_v<E> && //
1095 std::is_nothrow_swappable_v<E>))
1096 requires((std::is_swappable_v<E> && //
1097 std::is_move_constructible_v<E>)) //
1098 {
1099 using std::swap;
1100
1101 if (bool(*this) && bool(other)) {
1102 // is void
1103 } else if (!bool(*this) && !bool(other)) {
1104 swap(unex_, other.unex_);
1105 } else if (bool(*this) && !bool(other)) {
1106 std::construct_at(std::addressof(unex_), std::move(other.unex_));
1107 std::destroy_at(std::addressof(other.unex_));
1108
1109 swap(has_value_, other.has_value_);
1110 } else if (!bool(*this) && bool(other)) {
1111 other.swap(*this);
1112 }
1113 }
1114
1115 constexpr bool has_value() const { return has_value_; }
1116 constexpr explicit operator bool() const noexcept { return has_value(); }
1117
1118 // value accessors
1119
1120 constexpr void value() const & {
1121 static_assert(std::is_copy_constructible_v<E>);
1122
1123 if (!has_value()) {
1124 throw bad_expected_access(std::as_const(error()));
1125 }
1126 }
1127
1128 constexpr void value() && {
1129 static_assert(std::is_move_constructible_v<E>);
1130
1131 if (!has_value()) {
1132 throw bad_expected_access(std::as_const(error()));
1133 }
1134 }
1135
1136 // unchecked value access
1137
1138 // (3)
1139 constexpr void operator*() const noexcept { assert(has_value()); }
1140
1141 template <class U>
1142 constexpr value_type value_or(U &&v) const & {
1143 static_assert(
1144 std::is_copy_constructible_v<T> && std::is_convertible_v<U &&, T>,
1145 "T must be copy-constructible and convertible from U&&");
1146
1147 return has_value() ? **this : static_cast<T>(std::forward<U>(v));
1148 }
1149
1150 template <class U>
1151 constexpr value_type value_or(U &&v) && {
1152 static_assert(
1153 std::is_move_constructible_v<T> && std::is_convertible_v<U &&, T>,
1154 "T must be move-constructible and convertible from U&&");
1155
1156 return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v));
1157 }
1158
1159 // error accessors
1160 constexpr const error_type &error() const & { return unex_; }
1161 constexpr const error_type &&error() const && { return std::move(unex_); }
1162 constexpr error_type &error() & { return unex_; }
1163 constexpr error_type &&error() && { return std::move(unex_); }
1164
1165 // operator==
1166
1167 // (1) requires T is not cv void
1168
1169 // (2)
1170 template <class T2, class E2>
1171 friend constexpr bool operator==(const expected &lhs,
1172 const stdx::expected<T2, E2> &rhs)
1173 requires(std::is_void_v<T2>)
1174 {
1175 if (lhs.has_value() != rhs.has_value()) return false;
1176
1177 if (lhs.has_value()) return true;
1178
1179 return lhs.error() == rhs.error();
1180 }
1181
1182 // (3) requires T is not cv void
1183
1184 // (4)
1185 template <class E2>
1186 friend constexpr bool operator==(const expected &lhs,
1187 const unexpected<E2> &rhs) {
1188 if (lhs.has_value()) return false;
1189
1190 return static_cast<bool>(lhs.error() == rhs.error());
1191 }
1192 //
1193 // and_then
1194 //
1195
1196 template <class Func>
1197 constexpr auto and_then(Func &&func) & {
1198 return base::and_then_impl(*this, std::forward<Func>(func));
1199 }
1200
1201 template <class Func>
1202 constexpr auto and_then(Func &&func) && {
1203 return base::and_then_impl(std::move(*this), std::forward<Func>(func));
1204 }
1205
1206 template <class Func>
1207 constexpr auto and_then(Func &&func) const & {
1208 return base::and_then_impl(*this, std::forward<Func>(func));
1209 }
1210
1211 template <class Func>
1212 constexpr auto and_then(Func &&func) const && {
1213 return base::and_then_impl(std::move(*this), std::forward<Func>(func));
1214 }
1215
1216 //
1217 // or_else
1218 //
1219
1220 template <class Func>
1221 constexpr auto or_else(Func &&func) & {
1222 return base::or_else_impl(*this, std::forward<Func>(func));
1223 }
1224
1225 template <class Func>
1226 constexpr auto or_else(Func &&func) && {
1227 return base::or_else_impl(std::move(*this), std::forward<Func>(func));
1228 }
1229
1230 template <class Func>
1231 constexpr auto or_else(Func &&func) const & {
1232 return base::or_else_impl(*this, std::forward<Func>(func));
1233 }
1234
1235 template <class Func>
1236 constexpr auto or_else(Func &&func) const && {
1237 return base::or_else_impl(std::move(*this), std::forward<Func>(func));
1238 }
1239
1240 //
1241 // transform
1242 //
1243
1244 template <class Func>
1245 constexpr auto transform(Func &&func) & {
1246 return expected_transform_impl(*this, std::forward<Func>(func));
1247 }
1248
1249 template <class Func>
1250 constexpr auto transform(Func &&func) && {
1251 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
1252 }
1253
1254 template <class Func>
1255 constexpr auto transform(Func &&func) const & {
1256 return expected_transform_impl(*this, std::forward<Func>(func));
1257 }
1258
1259 template <class Func>
1260 constexpr auto transform(Func &&func) const && {
1261 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
1262 }
1263
1264 private:
1265 template <class U>
1266 void assign_unex(U &&u) {
1267 if (has_value_) {
1268 std::construct_at(std::addressof(unex_), std::forward<U>(u));
1269 has_value_ = false;
1270 } else {
1271 unex_ = std::forward<U>(u);
1272 }
1273 }
1274
1275 union {
1276 struct {
1277 } dummy_;
1278 E unex_;
1279 };
1280
1282};
1283
1284template <class Exp, class Func>
1285constexpr auto expected_transform_impl(Exp &&exp, Func &&func) {
1286 // type of the value that's passed to func
1287 using func_value_type = typename std::decay_t<Exp>::value_type;
1288
1289 if constexpr (std::is_void_v<func_value_type>) {
1290 using func_return_type = std::invoke_result_t<Func>;
1291 using result_type =
1293
1294 if (!exp.has_value()) {
1295 return result_type{stdx::unexpect, std::forward<Exp>(exp).error()};
1296 }
1297
1298 if constexpr (std::is_void_v<func_return_type>) {
1299 std::invoke(func);
1300 return result_type();
1301 } else {
1302 return result_type(std::invoke(func));
1303 }
1304 } else {
1305 using func_return_type = std::invoke_result_t<Func, func_value_type>;
1306 using result_type =
1308
1309 if (!exp.has_value()) {
1310 return result_type{stdx::unexpect, std::forward<Exp>(exp).error()};
1311 }
1312
1313 if constexpr (std::is_void_v<func_return_type>) {
1314 std::invoke(func, *std::forward<Exp>(exp));
1315 return result_type();
1316 } else {
1317 return result_type(std::invoke(func, *std::forward<Exp>(exp)));
1318 }
1319 }
1320}
1321
1322} // namespace stdx
1323
1324#endif
Definition: expected.h:904
E error_type
Definition: expected.h:915
constexpr expected(expected &&other)=default
T value_type
Definition: expected.h:914
constexpr expected(expected &&other) noexcept((std::is_nothrow_move_constructible_v< T >))
Definition: expected.h:936
constexpr expected() noexcept
Definition: expected.h:919
constexpr expected(const expected &other)
Definition: expected.h:924
bool has_value_
Definition: expected.h:1281
constexpr expected(const expected &other)=default
Definition: expected.h:286
constexpr expected & operator=(expected &&other)
Definition: expected.h:472
constexpr friend bool operator==(const expected &lhs, const unexpected< E2 > &rhs)
Definition: expected.h:787
constexpr T & emplace(Args &&...args) noexcept
Definition: expected.h:551
constexpr auto or_else(Func &&func) &
Definition: expected.h:823
constexpr auto or_else(Func &&func) &&
Definition: expected.h:828
constexpr auto and_then(Func &&func) &&
Definition: expected.h:804
constexpr expected(std::in_place_t, std::initializer_list< U > il, Args &&...args)
Definition: expected.h:431
constexpr expected & operator=(const unexpected< G > &other)
Definition: expected.h:507
constexpr const value_type && value() const &&
Definition: expected.h:680
constexpr auto and_then(Func &&func) const &
Definition: expected.h:809
constexpr auto transform(Func &&func) &
Definition: expected.h:847
constexpr G & rhs
Definition: expected.h:377
constexpr auto transform(Func &&func) const &
Definition: expected.h:857
E error_type
Definition: expected.h:299
constexpr expected(std::in_place_t, Args &&...args)
Definition: expected.h:425
constexpr value_type value_or(U &&v) &&
Definition: expected.h:751
constexpr const error_type & error() const &
Definition: expected.h:760
constexpr error_type && error() &&
Definition: expected.h:763
constexpr const value_type * operator->() const noexcept
Definition: expected.h:696
constexpr T & emplace(std::initializer_list< U > il, Args &&...args) noexcept
Definition: expected.h:566
constexpr bool has_value() const
Definition: expected.h:636
E unex_
Definition: expected.h:891
constexpr const value_type & value() const &
Definition: expected.h:656
constexpr auto transform(Func &&func) const &&
Definition: expected.h:862
constexpr value_type value_or(U &&v) const &
Definition: expected.h:741
constexpr expected & operator=(U &&val)
Definition: expected.h:491
constexpr expected(expected &&other)=default
constexpr auto or_else(Func &&func) const &&
Definition: expected.h:838
static constexpr bool can_value_convert_construct
Definition: expected.h:353
constexpr auto transform(Func &&func) &&
Definition: expected.h:852
constexpr value_type * operator->() noexcept
Definition: expected.h:703
constexpr ~expected()
Definition: expected.h:541
constexpr expected(stdx::unexpect_t, Args &&...args)
Definition: expected.h:440
static constexpr bool can_construct_from_value_type
Definition: expected.h:397
void assign_val(U &&u)
Definition: expected.h:868
T value_type
Definition: expected.h:298
constexpr value_type & value() &
Definition: expected.h:645
constexpr void swap(expected &other) noexcept((std::is_nothrow_move_constructible_v< T > &&//std::is_nothrow_move_constructible_v< E > &&//std::is_nothrow_swappable_v< T > &&//std::is_nothrow_swappable_v< E >))
Definition: expected.h:582
constexpr value_type && value() &&
Definition: expected.h:668
constexpr auto or_else(Func &&func) const &
Definition: expected.h:833
constexpr const value_type && operator*() const &&noexcept
Definition: expected.h:724
static constexpr bool constructor_is_explicit
Definition: expected.h:348
constexpr expected & operator=(unexpected< G > &&other)
Definition: expected.h:521
constexpr expected() noexcept(std::is_nothrow_default_constructible_v< T >)
Definition: expected.h:306
constexpr expected & operator=(expected const &other)
Definition: expected.h:454
constexpr error_type & error() &
Definition: expected.h:762
constexpr auto and_then(Func &&func) const &&
Definition: expected.h:814
bool has_value_
Definition: expected.h:899
constexpr const error_type && error() const &&
Definition: expected.h:761
constexpr const value_type & operator*() const &noexcept
Definition: expected.h:710
T val_
Definition: expected.h:890
constexpr auto and_then(Func &&func) &
Definition: expected.h:799
constexpr value_type && operator*() &&noexcept
Definition: expected.h:731
constexpr expected(expected &&other) noexcept((std::is_nothrow_move_constructible_v< E > &&std::is_nothrow_move_constructible_v< T >))
Definition: expected.h:332
constexpr expected(stdx::unexpect_t, std::initializer_list< U > il, Args &&...args)
Definition: expected.h:446
constexpr value_type & operator*() &noexcept
Definition: expected.h:717
constexpr expected(const expected &other) noexcept((std::is_nothrow_copy_constructible_v< T > &&std::is_nothrow_copy_constructible_v< E >))
Definition: expected.h:314
constexpr expected(const expected &other)=default
void assign_unex(U &&u)
Definition: expected.h:879
Definition: expected.h:112
constexpr unexpected(unexpected &&) noexcept=default
constexpr void swap(unexpected &other) noexcept(std::is_nothrow_swappable_v< E >)
Definition: expected.h:162
constexpr error_type && error() &&noexcept
Definition: expected.h:155
constexpr error_type & error() &noexcept
Definition: expected.h:153
constexpr unexpected & operator=(unexpected &&) noexcept=default
constexpr unexpected(std::in_place_t, std::initializer_list< U > il, Args &&...args) noexcept(std::is_nothrow_constructible_v< E, std::initializer_list< U > &, Args... >)
Definition: expected.h:138
error_type error_
Definition: expected.h:185
constexpr const error_type & error() const &noexcept
Definition: expected.h:154
constexpr unexpected(std::in_place_t, Args &&...args) noexcept(std::is_nothrow_constructible_v< E, Args... >)
Definition: expected.h:132
constexpr const error_type && error() const &&noexcept
Definition: expected.h:156
constexpr friend void swap(unexpected &lhs, unexpected &rhs) noexcept(noexcept(lhs.swap(rhs)))
Definition: expected.h:179
E error_type
Definition: expected.h:116
constexpr unexpected(const unexpected &)=default
constexpr unexpected & operator=(const unexpected &)=default
constexpr friend bool operator==(const unexpected &lhs, const stdx::unexpected< E2 > &rhs)
Definition: expected.h:174
error_type
Definition: error.h:36
#define U
Definition: ctype-tis620.cc:74
#define LIKELY(x)
Definition: expected.h:642
void destroy_at(T *ptr)
Definition: my_alloc.h:462
Header for compiler-dependent features.
bool operator==(const my_thread_handle &a, const my_thread_handle &b)
Definition: my_thread.h:151
void error(const char *format,...)
uint16_t value_type
Definition: vt100.h:184
bool transform(const dd::Spatial_reference_system *source_srs, const Geometry &in, const dd::Spatial_reference_system *target_srs, const char *func_name, std::unique_ptr< Geometry > *out) noexcept
Transforms a geometry from one SRS to another.
Definition: transform.cc:216
Definition: http_server_component.cc:34
static Value err()
Create a Value object that represents an error condition.
Definition: json_binary.cc:908
T value_or(T a, T b)
If a isn't set, return b.
Definition: loader.cc:605
Definition: gcs_xcom_synode.h:64
constexpr auto and_then_impl(Exp &&exp, Func &&func)
Definition: expected.h:241
constexpr auto or_else_impl(Exp &&exp, Func &&func)
Definition: expected.h:270
constexpr void reinit_expected(NewT *new_val, OldT *old_val, Args &&...args)
Definition: expected.h:210
constexpr bool is_unexpected
Definition: expected.h:204
constexpr bool is_expected
Definition: expected.h:198
Definition: bit.h:32
constexpr auto expected_transform_impl(Exp &&exp, Func &&func)
Definition: expected.h:1285
constexpr unexpect_t unexpect
Definition: expected.h:109
unexpected(E) -> unexpected< E >
static void swap(String &a, String &b) noexcept
Definition: sql_string.h:663
Definition: expected.h:105
unexpect_t()=default
Definition: dtoa.cc:595