MySQL 8.4.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 using std::swap;
166
167 swap(error_, other.error_);
168 }
169
170 // comparison
171
172 template <class E2>
173 friend constexpr bool operator==(const unexpected &lhs,
174 const stdx::unexpected<E2> &rhs) {
175 return lhs.error() == rhs.error();
176 }
177
178 friend constexpr void swap(unexpected &lhs, unexpected &rhs) noexcept(
179 noexcept(lhs.swap(rhs))) {
180 lhs.swap(rhs);
181 }
182
183 private:
185};
186
187// deduction guide
188template <class E>
190
191template <class T, class E>
192class expected;
193
194namespace impl {
195
196template <class T>
197constexpr bool is_expected = false;
198
199template <class T, class E>
200constexpr bool is_expected<expected<T, E>> = true;
201
202template <class T>
203constexpr bool is_unexpected = false;
204
205template <class T>
206constexpr bool is_unexpected<unexpected<T>> = true;
207
208template <class NewT, class OldT, class... Args>
209constexpr void reinit_expected(NewT *new_val, OldT *old_val, Args &&... args) {
210 if constexpr (std::is_nothrow_constructible_v<NewT, Args...>) {
211 std::destroy_at(old_val);
212 std::construct_at(new_val, std::forward<Args>(args)...);
213 } else if constexpr (std::is_nothrow_move_constructible_v<NewT>) {
214 NewT tmp(std::forward<Args>(args)...);
215
216 std::destroy_at(old_val);
217 std::construct_at(new_val, std::move(tmp));
218 } else {
219 OldT tmp(std::move(*old_val));
220
221 std::destroy_at(old_val);
222 try {
223 std::construct_at(new_val, std::forward<Args>(args)...);
224 } catch (...) {
225 std::construct_at(old_val, std::move(tmp));
226 throw;
227 }
228 }
229}
230
231} // namespace impl
232
233namespace base {
234
235template <class Exp, class Func,
236 typename value_type = typename std::decay_t<Exp>::value_type>
237requires(std::is_void_v<value_type> ? std::is_invocable_v<Func>
238 : std::is_invocable_v<Func, value_type>) //
239 constexpr auto and_then_impl(Exp &&exp, Func &&func) {
240 if constexpr (std::is_void_v<value_type>) {
241 using Ret = std::invoke_result_t<Func>;
242
243 static_assert(stdx::impl::is_expected<Ret>,
244 "Func must return a stdx::expected<>");
245
246 if (exp.has_value()) {
247 return std::invoke(func);
248 } else {
249 return Ret{stdx::unexpect, std::forward<Exp>(exp).error()};
250 }
251 } else {
252 using Ret = std::invoke_result_t<Func, value_type>;
253
254 static_assert(stdx::impl::is_expected<Ret>,
255 "Func must return a stdx::expected<>");
256
257 if (exp.has_value()) {
258 return std::invoke(func, *std::forward<Exp>(exp));
259 } else {
260 return Ret{stdx::unexpect, std::forward<Exp>(exp).error()};
261 }
262 }
263}
264
265template <class Exp, class Func,
266 typename error_type = typename std::decay_t<Exp>::error_type>
267requires std::is_invocable_v<Func, error_type> //
268 constexpr auto or_else_impl(Exp &&exp, Func &&func) {
269 static_assert(
270 std::is_same_v<
271 std::remove_cvref_t<std::invoke_result_t<Func, error_type>>, Exp>,
272 "Func must return an expected<>");
273
274 if (exp.has_value()) {
275 return std::forward<Exp>(exp);
276 }
277
278 return std::invoke(std::forward<Func>(func), std::forward<Exp>(exp).error());
279}
280
281} // namespace base
282
283template <class T, class E>
284class expected {
285 public:
286 static_assert(!std::is_void_v<E>, "E must not be void");
287 static_assert(!std::is_reference_v<T>, "T must not be a reference");
288 static_assert(!std::is_function_v<T>, "T must not be a function");
289 static_assert(!std::is_same_v<std::remove_cv_t<T>, std::in_place_t>,
290 "T must not be std::in_place_t");
291 static_assert(!std::is_same_v<std::remove_cv_t<T>, unexpect_t>,
292 "T must not be stdx::unexpect_t");
293 static_assert(!std::is_same_v<T, std::remove_cv<unexpected<E>>>,
294 "T must not be unexpected<E>");
295
296 using value_type = T;
297 using error_type = E;
299
300 template <typename U>
302
303 // (1)
304 constexpr expected() //
305 noexcept(std::is_nothrow_default_constructible_v<T>) //
306 requires std::is_default_constructible_v<T> //
307 : val_{}, has_value_(true) {}
308
309 // (2)
310 constexpr expected(const expected &other) = default;
311
312 constexpr expected(const expected &other) //
313 noexcept((std::is_nothrow_copy_constructible_v<T> &&
314 std::is_nothrow_copy_constructible_v<E>)) //
315 requires((std::is_copy_constructible_v<T> &&
316 std::is_copy_constructible_v<E> &&
317 (!std::is_trivially_copy_constructible_v<T> ||
318 !std::is_trivially_copy_constructible_v<E>)))
319 : has_value_{other.has_value()} {
320 if (has_value()) {
321 std::construct_at(std::addressof(val_), other.val_);
322 } else {
323 std::construct_at(std::addressof(unex_), other.unex_);
324 }
325 }
326
327 // (3)
328 constexpr expected(expected &&other) = default;
329
330 constexpr expected(expected &&other) //
331 noexcept((std::is_nothrow_move_constructible_v<E> &&
332 std::is_nothrow_move_constructible_v<T>)) //
333 requires((std::is_move_constructible_v<T> &&
334 std::is_move_constructible_v<E> &&
335 (!std::is_trivially_move_constructible_v<T> ||
336 !std::is_trivially_move_constructible_v<E>))) //
337 : has_value_{other.has_value()} {
338 if (has_value()) {
339 std::construct_at(std::addressof(val_), std::move(other.val_));
340 } else {
341 std::construct_at(std::addressof(unex_), std::move(other.unex_));
342 }
343 }
344
345 template <class UF, class GF>
346 static constexpr bool constructor_is_explicit =
347 !std::is_convertible_v<UF, T> || !std::is_convertible_v<GF, E>;
348
349 //
350 template <class U, class G, class UF, class GF>
351 static constexpr bool can_value_convert_construct =
352 (std::is_constructible_v<T, UF> && //
353 std::is_constructible_v<E, GF> &&
354 !std::is_constructible_v<T, expected<U, G> &> &&
355 !std::is_constructible_v<T, expected<U, G>> &&
356 !std::is_constructible_v<T, const expected<U, G> &> &&
357 !std::is_constructible_v<T, const expected<U, G>> &&
358 !std::is_convertible_v<expected<U, G> &, T> &&
359 !std::is_convertible_v<expected<U, G>, T> &&
360 !std::is_convertible_v<const expected<U, G> &, T> &&
361 !std::is_convertible_v<const expected<U, G>, T> &&
362 !std::is_constructible_v<unexpected<E>, expected<U, G> &> &&
363 !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
364 !std::is_constructible_v<unexpected<E>, const expected<U, G> &> &&
365 !std::is_constructible_v<unexpected<E>, const expected<U, G>>);
366
367 // (4)
368 template <class U, class G, class UF = std::add_lvalue_reference_t<const U>,
369 class GF = const G &>
370 constexpr explicit(constructor_is_explicit<UF, GF>)
372 requires can_value_convert_construct<U, G, UF, GF>
373 : has_value_{rhs.has_value()} {
374 if (rhs.has_value()) {
375 std::construct_at(std::addressof(val_), std::forward<UF>(*rhs));
376 } else {
377 std::construct_at(std::addressof(unex_), std::forward<GF>(rhs.error()));
378 }
379 }
380
381 // (5)
382 template <class U, class G, class UF = U, class GF = G>
383 constexpr explicit(constructor_is_explicit<UF, GF>)
385 requires can_value_convert_construct<U, G, UF, GF>
386 : has_value_{rhs.has_value()} {
387 if (rhs.has_value()) {
388 std::construct_at(std::addressof(val_), std::forward<UF>(*rhs));
389 } else {
390 std::construct_at(std::addressof(unex_), std::forward<GF>(rhs.error()));
391 }
392 }
393
394 template <class U>
395 static constexpr bool can_construct_from_value_type =
396 !std::is_same_v<std::in_place_t, std::remove_cvref_t<U>> &&
397 !std::is_same_v<expected, std::remove_cvref_t<U>> &&
398 std::is_constructible_v<T, U> &&
399 !impl::is_unexpected<std::remove_cvref_t<U>> &&
400 !impl::is_expected<std::remove_cvref_t<T>>;
401
402 // (6)
403 template <class U = T>
404 constexpr explicit(!std::is_convertible_v<U, T>) expected(U &&val) //
405 requires can_construct_from_value_type<U>
406 : val_(std::forward<U>(val)), has_value_{true} {}
407
408 // (7)
409 template <class G>
410 constexpr explicit(!std::is_convertible_v<const G &, E>)
411 expected(const unexpected<G> &err) //
412 requires std::is_constructible_v<E, const G &>
413 : unex_(err.error()), has_value_{false} {}
414
415 // (8)
416 template <class G>
417 constexpr explicit(!std::is_convertible_v<G, E>)
419 requires std::is_constructible_v<E, G>
420 : unex_(std::move(err.error())), has_value_{false} {}
421
422 // (9)
423 template <class... Args>
424 constexpr explicit expected(std::in_place_t, Args &&... args) //
425 requires std::is_constructible_v<T, Args...>
426 : val_(std::forward<Args>(args)...), has_value_{true} {}
427
428 // (10)
429 template <class U, class... Args>
430 constexpr explicit expected(std::in_place_t, std::initializer_list<U> il,
431 Args &&... args) //
432 requires std::is_constructible_v<T, std::initializer_list<U> &, Args...>
433 : val_(il, std::forward<Args>(args)...), has_value_{true} {}
434
435 // (11) skipped, only for T-is-void
436
437 // (12)
438 template <class... Args>
439 constexpr explicit expected(stdx::unexpect_t, Args &&... args) //
440 requires std::is_constructible_v<E, Args &&...>
441 : unex_(std::forward<Args>(args)...), has_value_{false} {}
442
443 // (13)
444 template <class U, class... Args>
445 constexpr explicit expected(stdx::unexpect_t, std::initializer_list<U> il,
446 Args &&... args) //
447 requires std::is_constructible_v<E, std::initializer_list<U> &, Args...>
448 : unex_(il, std::forward<Args>(args)...), has_value_{false} {}
449
450 // assignment
451
452 // (1)
453 constexpr expected &operator=(expected const &other) //
454 requires((std::is_copy_assignable_v<T> && //
455 std::is_copy_constructible_v<T> && //
456 std::is_copy_assignable_v<E> && //
457 std::is_copy_constructible_v<E> && //
458 (std::is_nothrow_move_constructible_v<T> ||
459 std::is_nothrow_move_constructible_v<E>))) {
460 if (other.has_value()) {
461 assign_val(other.val_);
462 } else {
463 assign_unex(other.unex_);
464 }
465
466 return *this;
467 }
468
469 // (2)
470 constexpr expected &operator=(expected &&other) //
471 requires((std::is_move_assignable_v<T> && //
472 std::is_move_constructible_v<T> && //
473 std::is_move_assignable_v<E> && //
474 std::is_move_constructible_v<E> && //
475 (std::is_nothrow_move_constructible_v<T> ||
476 std::is_nothrow_move_constructible_v<E>))) {
477 if (other.has_value()) {
478 assign_val(std::move(other.val_));
479 } else {
480 assign_unex(std::move(other.unex_));
481 }
482
483 return *this;
484 }
485
486 // (3) assign from expected value
487 template <class U = T>
488 constexpr expected &operator=(U &&val) //
489 requires((!std::is_same_v<expected<T, E>, std::remove_cvref_t<U>> && //
490 !impl::is_unexpected<std::remove_cvref_t<U>> && //
491 std::is_constructible_v<T, U> && //
492 std::is_assignable_v<T &, U> && //
493 (std::is_nothrow_constructible_v<T, U> || //
494 std::is_nothrow_move_constructible_v<T> || //
495 std::is_nothrow_move_constructible_v<E>))) {
496 assign_val(std::forward<U>(val));
497
498 return *this;
499 }
500
501 // (4)
502 template <class G, class GF = const G &>
503 constexpr expected &operator=(const unexpected<G> &other) //
504 requires((std::is_constructible_v<E, GF> && //
505 std::is_assignable_v<E &, GF> && //
506 (std::is_nothrow_constructible_v<E, GF> || //
507 std::is_nothrow_move_constructible_v<T> || //
508 std::is_nothrow_move_constructible_v<E>))) {
509 assign_unex(other.error());
510
511 return *this;
512 }
513
514 // (5)
515 template <class G, class GF = G>
516 constexpr expected &operator=(unexpected<G> &&other) //
517 requires((std::is_constructible_v<E, GF> && //
518 std::is_assignable_v<E &, GF> && //
519 (std::is_nothrow_constructible_v<E, GF> || //
520 std::is_nothrow_move_constructible_v<T> || //
521 std::is_nothrow_move_constructible_v<E>))) {
522 assign_unex(std::move(other.error()));
523
524 return *this;
525 }
526
527 // destruct
528#if defined(CXX_HAS_CONDITIONAL_TRIVIAL_DESTRUCTOR)
529 constexpr ~expected() requires((std::is_trivially_destructible_v<T> &&
530 std::is_trivially_destructible_v<E>)) =
531 default;
532#endif
533
534 constexpr ~expected() {
535 if (has_value()) {
536 std::destroy_at(std::addressof(val_));
537 } else {
538 std::destroy_at(std::addressof(unex_));
539 }
540 }
541
542 // emplace
543 template <class... Args>
544 constexpr T &emplace(Args &&... args) noexcept //
545 requires(std::is_nothrow_constructible_v<T, Args...>) {
546 if (has_value()) {
547 std::destroy_at(std::addressof(val_));
548 } else {
549 std::destroy_at(std::addressof(unex_));
550 has_value_ = true;
551 }
552
553 return *std::construct_at(std::addressof(val_),
554 std::forward<Args>(args)...);
555 }
556
557 template <class U, class... Args>
558 constexpr T &emplace(std::initializer_list<U> il,
559 Args &&... args) noexcept //
560 requires(std::is_nothrow_constructible_v<T, std::initializer_list<U> &,
561 Args...>) {
562 if (has_value()) {
563 std::destroy_at(std::addressof(val_));
564 } else {
565 std::destroy_at(std::addressof(unex_));
566 has_value_ = true;
567 }
568
569 return *std::construct_at(std::addressof(val_), il,
570 std::forward<Args>(args)...);
571 }
572
573 // swap
574 constexpr void swap(expected &other) //
575 noexcept((std::is_nothrow_move_constructible_v<T> && //
576 std::is_nothrow_move_constructible_v<E> && //
577 std::is_nothrow_swappable_v<T> && //
578 std::is_nothrow_swappable_v<E>)) //
579 requires((std::is_swappable_v<T> && //
580 std::is_swappable_v<E> && //
581 std::is_move_constructible_v<T> && //
582 std::is_move_constructible_v<E> && //
583 (std::is_nothrow_move_constructible_v<T> || //
584 std::is_nothrow_move_constructible_v<E>))) {
585 using std::swap;
586
587 if (bool(*this) && bool(other)) {
588 swap(val_, other.val_);
589 } else if (!bool(*this) && !bool(other)) {
590 swap(unex_, other.unex_);
591 } else if (bool(*this) && !bool(other)) {
592 if constexpr (std::is_nothrow_move_constructible_v<E>) {
593 error_type tmp(std::move(other.error()));
594
595 std::destroy_at(std::addressof(other.unex_));
596 try {
597 std::construct_at(std::addressof(other.val_), std::move(val_));
598 std::destroy_at(std::addressof(val_));
599 std::construct_at(std::addressof(unex_), std::move(tmp));
600 } catch (...) {
601 // restore old value.
602 std::construct_at(std::addressof(other.unex_), std::move(tmp));
603 throw;
604 }
605 } else {
606 value_type tmp(std::move(val_));
607
608 std::destroy_at(std::addressof(val_));
609 try {
610 std::construct_at(std::addressof(unex_), std::move(other.unex_));
611 std::destroy_at(std::addressof(other.unex_));
612 std::construct_at(std::addressof(val_), std::move(tmp));
613 } catch (...) {
614 // restore old value.
615 std::construct_at(std::addressof(val_), std::move(tmp));
616 throw;
617 }
618 }
619
620 has_value_ = false;
621 other.has_value_ = true;
622 } else if (!bool(*this) && bool(other)) {
623 other.swap(*this);
624 }
625 }
626
627 constexpr bool has_value() const { return has_value_; }
628 constexpr explicit operator bool() const noexcept { return has_value(); }
629
630 // value accessors
631
632 // the macro only exists for clang-format-10 to not get the formatting wrong.
633#define LIKELY(x) (x) [[likely]]
634
635 // (1)
636 constexpr value_type &value() & {
637 static_assert(std::is_copy_constructible_v<E>,
638 "error-type must be copy-constructible");
639 if LIKELY (has_value()) {
640 return val_;
641 }
642
643 throw bad_expected_access(std::as_const(error()));
644 }
645
646 // (2)
647 constexpr const value_type &value() const & {
648 static_assert(std::is_copy_constructible_v<E>,
649 "error-type must be copy-constructible");
650
651 if LIKELY (has_value()) {
652 return val_;
653 }
654
655 throw bad_expected_access(std::as_const(error()));
656 }
657
658 // (3)
659 constexpr value_type &&value() && {
660 static_assert(std::is_copy_constructible_v<E> &&
661 std::is_constructible_v<E, decltype(std::move(error()))>);
662
663 if LIKELY (has_value()) {
664 return std::move(val_);
665 }
666
667 throw bad_expected_access(std::move(error()));
668 }
669
670 // (4)
671 constexpr const value_type &&value() const && {
672 static_assert(std::is_copy_constructible_v<E> &&
673 std::is_constructible_v<E, decltype(std::move(error()))>);
674
675 if LIKELY (has_value()) {
676 return std::move(val_);
677 }
678
679 throw bad_expected_access(std::move(error()));
680 }
681
682#undef LIKELY
683
684 // unchecked value access
685
686 // (1)
687 constexpr const value_type *operator->() const noexcept {
688 assert(has_value());
689
690 return std::addressof(val_);
691 }
692
693 // (2)
694 constexpr value_type *operator->() noexcept {
695 assert(has_value());
696
697 return std::addressof(val_);
698 }
699
700 // (3)
701 constexpr const value_type &operator*() const &noexcept {
702 assert(has_value());
703
704 return val_;
705 }
706
707 // (4)
708 constexpr value_type &operator*() &noexcept {
709 assert(has_value());
710
711 return val_;
712 }
713
714 // (5)
715 constexpr const value_type &&operator*() const &&noexcept {
716 assert(has_value());
717
718 return std::move(val_);
719 }
720
721 // (6)
722 constexpr value_type &&operator*() &&noexcept {
723 assert(has_value());
724
725 return std::move(val_);
726 }
727
728 // value_or
729
730 // (1)
731 template <class U>
732 constexpr value_type value_or(U &&v) const & {
733 static_assert(
734 std::is_copy_constructible_v<T> && std::is_convertible_v<U &&, T>,
735 "T must be copy-constructible and convertible from U&&");
736
737 return has_value() ? **this : static_cast<T>(std::forward<U>(v));
738 }
739
740 // (2)
741 template <class U>
742 constexpr value_type value_or(U &&v) && {
743 static_assert(
744 std::is_move_constructible_v<T> && std::is_convertible_v<U &&, T>,
745 "T must be move-constructible and convertible from U&&");
746
747 return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v));
748 }
749
750 // error accessors
751 constexpr const error_type &error() const & { return unex_; }
752 constexpr const error_type &&error() const && { return std::move(unex_); }
753 constexpr error_type &error() & { return unex_; }
754 constexpr error_type &&error() && { return std::move(unex_); }
755
756 // operator==
757
758 // (1)
759 template <class T2, class E2>
760 requires(!std::is_void_v<T2>) //
761 friend constexpr bool
762 operator==(const expected &lhs, const stdx::expected<T2, E2> &rhs) {
763 if (lhs.has_value() != rhs.has_value()) return false;
764
765 if (!lhs.has_value()) return lhs.error() == rhs.error();
766 return static_cast<bool>(*lhs == *rhs);
767 }
768
769 // (3)
770 template <class T2>
771 requires(!impl::is_expected<T2>) //
772 friend constexpr bool
773 operator==(const expected &lhs, const T2 &rhs) {
774 return lhs.has_value() && static_cast<bool>(*lhs == rhs);
775 }
776
777 // (4)
778 template <class E2>
779 friend constexpr bool operator==(const expected &lhs,
780 const unexpected<E2> &rhs) {
781 if (lhs.has_value()) return false;
782
783 return static_cast<bool>(lhs.error() == rhs.error());
784 }
785
786 //
787 // and_then
788 //
789
790 template <class Func>
791 constexpr auto and_then(Func &&func) & {
792 return base::and_then_impl(*this, std::forward<Func>(func));
793 }
794
795 template <class Func>
796 constexpr auto and_then(Func &&func) && {
797 return base::and_then_impl(std::move(*this), std::forward<Func>(func));
798 }
799
800 template <class Func>
801 constexpr auto and_then(Func &&func) const & {
802 return base::and_then_impl(*this, std::forward<Func>(func));
803 }
804
805 template <class Func>
806 constexpr auto and_then(Func &&func) const && {
807 return base::and_then_impl(std::move(*this), std::forward<Func>(func));
808 }
809
810 //
811 // or_else
812 //
813
814 template <class Func>
815 constexpr auto or_else(Func &&func) & {
816 return base::or_else_impl(*this, std::forward<Func>(func));
817 }
818
819 template <class Func>
820 constexpr auto or_else(Func &&func) && {
821 return base::or_else_impl(std::move(*this), std::forward<Func>(func));
822 }
823
824 template <class Func>
825 constexpr auto or_else(Func &&func) const & {
826 return base::or_else_impl(*this, std::forward<Func>(func));
827 }
828
829 template <class Func>
830 constexpr auto or_else(Func &&func) const && {
831 return base::or_else_impl(std::move(*this), std::forward<Func>(func));
832 }
833
834 //
835 // transform
836 //
837
838 template <class Func>
839 constexpr auto transform(Func &&func) & {
840 return expected_transform_impl(*this, std::forward<Func>(func));
841 }
842
843 template <class Func>
844 constexpr auto transform(Func &&func) && {
845 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
846 }
847
848 template <class Func>
849 constexpr auto transform(Func &&func) const & {
850 return expected_transform_impl(*this, std::forward<Func>(func));
851 }
852
853 template <class Func>
854 constexpr auto transform(Func &&func) const && {
855 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
856 }
857
858 private:
859 template <class U>
860 void assign_val(U &&u) {
861 if (has_value_) {
862 val_ = std::forward<U>(u);
863 } else {
864 impl::reinit_expected(std::addressof(val_), std::addressof(unex_),
865 std::forward<U>(u));
866 has_value_ = true;
867 }
868 }
869
870 template <class U>
871 void assign_unex(U &&u) {
872 if (has_value_) {
873 impl::reinit_expected(std::addressof(unex_), std::addressof(val_),
874 std::forward<U>(u));
875 has_value_ = false;
876 } else {
877 unex_ = std::forward<U>(u);
878 }
879 }
880
881 union {
884#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 12
885 // workaround GCC 10/11's "maybe-uninitialized"
886 // GCC 12 and 13 do not report it.
887 volatile char gcc_pr80635_workaround_maybe_uninitialized_;
888#endif
889 };
890
892};
893
894template <class T, class E>
895requires(std::is_void_v<T>) //
897 public:
898 static_assert(!std::is_void_v<E>, "E must not be void");
899 static_assert(!std::is_reference_v<T>, "T must not be a reference");
900 static_assert(!std::is_same_v<T, std::remove_cv<std::in_place_t>>,
901 "T must not be std::in_place_t");
902 static_assert(!std::is_same_v<T, std::remove_cv<unexpected<E>>>,
903 "T must not be unexpected<E>");
904 static_assert(!std::is_reference_v<E>, "E must not be a reference");
905
906 using value_type = T;
907 using error_type = E;
909
910 // (1)
911 constexpr expected() noexcept : dummy_(), has_value_(true) {}
912
913 // (2)
914 constexpr expected(const expected &other) = default;
915
916 constexpr expected(const expected &other) requires(
917 (std::is_copy_constructible_v<E> &&
918 !std::is_trivially_copy_constructible_v<E>))
919 : dummy_(), has_value_{other.has_value()} {
920 if (!has_value()) {
921 std::construct_at(std::addressof(unex_), other.unex_);
922 }
923 }
924
925 // (3)
926 constexpr expected(expected &&other) = default;
927
928 constexpr expected(expected &&other) //
929 noexcept((std::is_nothrow_move_constructible_v<T>)) //
930 requires((std::is_move_constructible_v<E> &&
931 !std::is_trivially_move_constructible_v<E>)) //
932 : dummy_(), has_value_{other.has_value()} {
933 if (!has_value()) {
934 std::construct_at(std::addressof(unex_), std::move(other.unex_));
935 }
936 }
937
938 template <class UF, class GF>
939 static constexpr bool constructor_is_explicit =
940 (!std::is_convertible_v<UF, T> || !std::is_convertible_v<GF, E>);
941
942 template <class U, class G, class UF, class GF>
943 static constexpr bool can_value_convert_construct =
944 (std::is_void_v<U> && std::is_constructible_v<E, GF> &&
945 !std::is_constructible_v<unexpected<E>, expected<U, G> &> &&
946 !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
947 !std::is_constructible_v<unexpected<E>, const expected<U, G> &> &&
948 !std::is_constructible_v<unexpected<E>, const expected<U, G>>);
949
950 // (4)
951 template <class U, class G, class UF = std::add_lvalue_reference_t<const U>,
952 class GF = const G &>
953 constexpr explicit(constructor_is_explicit<UF, GF>) //
955 requires can_value_convert_construct<U, G, UF, GF>
956 : dummy_(), has_value_{rhs.has_value()} {
957 if (!rhs.has_value()) {
958 std::construct_at(std::addressof(unex_), rhs.error());
959 }
960 }
961
962 // (5)
963 template <class U, class G, class UF = U, class GF = G>
964 constexpr explicit(constructor_is_explicit<UF, GF>) //
965 expected(expected<U, G> &&rhs) //
966 requires can_value_convert_construct<U, G, UF, GF>
967 : dummy_(), has_value_{rhs.has_value()} {
968 if (!rhs.has_value()) {
969 std::construct_at(std::addressof(unex_), std::move(rhs.error()));
970 }
971 }
972
973 // (6) requires T is not cv void.
974
975 // (7)
976 template <class G>
977 constexpr explicit(!std::is_convertible_v<const G &, E>)
978 expected(const unexpected<G> &err) //
979 requires std::is_constructible_v<E, const G &>
980 : unex_(err.error()), has_value_{false} {}
981
982 // (8)
983 template <class G>
984 constexpr explicit(!std::is_convertible_v<G, E>)
985 expected(unexpected<G> &&err) //
986 requires std::is_constructible_v<E, G>
987 : unex_(std::move(err.error())), has_value_{false} {}
988
989 // (9) requires T is not cv void.
990
991 // (10) requires T is not cv void.
992
993 // (11)
994 template <class... Args>
995 constexpr explicit expected(std::in_place_t) : has_value_{true} {}
996
997 // (12)
998 template <class... Args>
999 constexpr explicit expected(stdx::unexpect_t, Args &&... args) //
1000 requires std::is_constructible_v<E, Args...>
1001 : unex_(std::forward<Args>(args)...), has_value_{false} {}
1002
1003 // (13)
1004 template <class U, class... Args>
1005 constexpr explicit expected(stdx::unexpect_t, std::initializer_list<U> il,
1006 Args &&... args) //
1007 requires std::is_constructible_v<E, std::initializer_list<U> &, Args...>
1008 : unex_(il, std::forward<Args>(args)...), has_value_{false} {}
1009
1010 // assignment
1011
1012 // (1)
1013 constexpr expected &operator=(expected const &other) //
1014 requires((std::is_copy_assignable_v<E> && //
1015 std::is_copy_constructible_v<E>)) {
1016 if (other.has_value()) {
1017 emplace(); // destroys unex_ and sets has_value_ = true
1018 } else {
1019 assign_unex(other.unex_);
1020 }
1021
1022 return *this;
1023 }
1024
1025 // (2)
1026 constexpr expected &operator=(expected &&other) //
1027 requires((std::is_move_assignable_v<E> && //
1028 std::is_move_constructible_v<E>)) {
1029 if (other.has_value()) {
1030 emplace();
1031 } else {
1032 assign_unex(other.unex_);
1033 }
1034 return *this;
1035 }
1036
1037 // (3) requires T is not cv void.
1038
1039 // (4)
1040 template <class G, class GF = const G &>
1041 constexpr expected &operator=(const unexpected<G> &other) //
1042 requires((std::is_constructible_v<E, GF> && //
1043 std::is_assignable_v<E &, GF>)) {
1044 assign_unex(other.error());
1045
1046 return *this;
1047 }
1048
1049 // (5)
1050 template <class G, class GF = G>
1051 constexpr expected &operator=(unexpected<G> &&other) //
1052 requires(std::is_constructible_v<E, GF> && //
1053 std::is_assignable_v<E &, GF>) {
1054 assign_unex(std::move(other.error()));
1055
1056 return *this;
1057 }
1058
1059 // destruct
1060#if defined(CXX_HAS_CONDITIONAL_TRIVIAL_DESTRUCTOR)
1061 constexpr ~expected() requires((std::is_trivially_destructible_v<E>)) =
1062 default;
1063#endif
1064
1065 constexpr ~expected() {
1066 if (!has_value()) {
1067 std::destroy_at(std::addressof(unex_));
1068 }
1069 }
1070
1071 // emplace
1072 constexpr void emplace() noexcept {
1073 if (!has_value()) {
1074 std::destroy_at(std::addressof(unex_));
1075 has_value_ = true;
1076 }
1077 }
1078
1079 // swap
1080 constexpr void swap(expected &other) //
1081 noexcept((std::is_nothrow_move_constructible_v<E> && //
1082 std::is_nothrow_swappable_v<E>)) //
1083 requires((std::is_swappable_v<E> && //
1084 std::is_move_constructible_v<E>)) //
1085 {
1086 using std::swap;
1087
1088 if (bool(*this) && bool(other)) {
1089 // is void
1090 } else if (!bool(*this) && !bool(other)) {
1091 swap(unex_, other.unex_);
1092 } else if (bool(*this) && !bool(other)) {
1093 std::construct_at(std::addressof(unex_), std::move(other.unex_));
1094 std::destroy_at(std::addressof(other.unex_));
1095
1096 swap(has_value_, other.has_value_);
1097 } else if (!bool(*this) && bool(other)) {
1098 other.swap(*this);
1099 }
1100 }
1101
1102 constexpr bool has_value() const { return has_value_; }
1103 constexpr explicit operator bool() const noexcept { return has_value(); }
1104
1105 // value accessors
1106
1107 constexpr void value() const & {
1108 static_assert(std::is_copy_constructible_v<E>);
1109
1110 if (!has_value()) {
1111 throw bad_expected_access(std::as_const(error()));
1112 }
1113 }
1114
1115 constexpr void value() && {
1116 static_assert(std::is_move_constructible_v<E>);
1117
1118 if (!has_value()) {
1119 throw bad_expected_access(std::as_const(error()));
1120 }
1121 }
1122
1123 // unchecked value access
1124
1125 // (3)
1126 constexpr void operator*() const noexcept { assert(has_value()); }
1127
1128 template <class U>
1129 constexpr value_type value_or(U &&v) const & {
1130 static_assert(
1131 std::is_copy_constructible_v<T> && std::is_convertible_v<U &&, T>,
1132 "T must be copy-constructible and convertible from U&&");
1133
1134 return has_value() ? **this : static_cast<T>(std::forward<U>(v));
1135 }
1136
1137 template <class U>
1138 constexpr value_type value_or(U &&v) && {
1139 static_assert(
1140 std::is_move_constructible_v<T> && std::is_convertible_v<U &&, T>,
1141 "T must be move-constructible and convertible from U&&");
1142
1143 return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v));
1144 }
1145
1146 // error accessors
1147 constexpr const error_type &error() const & { return unex_; }
1148 constexpr const error_type &&error() const && { return std::move(unex_); }
1149 constexpr error_type &error() & { return unex_; }
1150 constexpr error_type &&error() && { return std::move(unex_); }
1151
1152 // operator==
1153
1154 // (1) requires T is not cv void
1155
1156 // (2)
1157 template <class T2, class E2>
1158 friend constexpr bool operator==(const expected &lhs,
1159 const stdx::expected<T2, E2> &rhs) //
1160 requires(std::is_void_v<T2>) {
1161 if (lhs.has_value() != rhs.has_value()) return false;
1162
1163 if (lhs.has_value()) return true;
1164
1165 return lhs.error() == rhs.error();
1166 }
1167
1168 // (3) requires T is not cv void
1169
1170 // (4)
1171 template <class E2>
1172 friend constexpr bool operator==(const expected &lhs,
1173 const unexpected<E2> &rhs) {
1174 if (lhs.has_value()) return false;
1175
1176 return static_cast<bool>(lhs.error() == rhs.error());
1177 }
1178 //
1179 // and_then
1180 //
1181
1182 template <class Func>
1183 constexpr auto and_then(Func &&func) & {
1184 return base::and_then_impl(*this, std::forward<Func>(func));
1185 }
1186
1187 template <class Func>
1188 constexpr auto and_then(Func &&func) && {
1189 return base::and_then_impl(std::move(*this), std::forward<Func>(func));
1190 }
1191
1192 template <class Func>
1193 constexpr auto and_then(Func &&func) const & {
1194 return base::and_then_impl(*this, std::forward<Func>(func));
1195 }
1196
1197 template <class Func>
1198 constexpr auto and_then(Func &&func) const && {
1199 return base::and_then_impl(std::move(*this), std::forward<Func>(func));
1200 }
1201
1202 //
1203 // or_else
1204 //
1205
1206 template <class Func>
1207 constexpr auto or_else(Func &&func) & {
1208 return base::or_else_impl(*this, std::forward<Func>(func));
1209 }
1210
1211 template <class Func>
1212 constexpr auto or_else(Func &&func) && {
1213 return base::or_else_impl(std::move(*this), std::forward<Func>(func));
1214 }
1215
1216 template <class Func>
1217 constexpr auto or_else(Func &&func) const & {
1218 return base::or_else_impl(*this, std::forward<Func>(func));
1219 }
1220
1221 template <class Func>
1222 constexpr auto or_else(Func &&func) const && {
1223 return base::or_else_impl(std::move(*this), std::forward<Func>(func));
1224 }
1225
1226 //
1227 // transform
1228 //
1229
1230 template <class Func>
1231 constexpr auto transform(Func &&func) & {
1232 return expected_transform_impl(*this, std::forward<Func>(func));
1233 }
1234
1235 template <class Func>
1236 constexpr auto transform(Func &&func) && {
1237 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
1238 }
1239
1240 template <class Func>
1241 constexpr auto transform(Func &&func) const & {
1242 return expected_transform_impl(*this, std::forward<Func>(func));
1243 }
1244
1245 template <class Func>
1246 constexpr auto transform(Func &&func) const && {
1247 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
1248 }
1249
1250 private:
1251 template <class U>
1252 void assign_unex(U &&u) {
1253 if (has_value_) {
1254 std::construct_at(std::addressof(unex_), std::forward<U>(u));
1255 has_value_ = false;
1256 } else {
1257 unex_ = std::forward<U>(u);
1258 }
1259 }
1260
1261 union {
1262 struct {
1263 } dummy_;
1264 E unex_;
1265 };
1266
1268};
1269
1270template <class Exp, class Func>
1271constexpr auto expected_transform_impl(Exp &&exp, Func &&func) {
1272 // type of the value that's passed to func
1273 using func_value_type = typename std::decay_t<Exp>::value_type;
1274
1275 if constexpr (std::is_void_v<func_value_type>) {
1276 using func_return_type = std::invoke_result_t<Func>;
1277 using result_type =
1279
1280 if (!exp.has_value()) {
1281 return result_type{stdx::unexpect, std::forward<Exp>(exp).error()};
1282 }
1283
1284 if constexpr (std::is_void_v<func_return_type>) {
1285 std::invoke(func);
1286 return result_type();
1287 } else {
1288 return result_type(std::invoke(func));
1289 }
1290 } else {
1291 using func_return_type = std::invoke_result_t<Func, func_value_type>;
1292 using result_type =
1294
1295 if (!exp.has_value()) {
1296 return result_type{stdx::unexpect, std::forward<Exp>(exp).error()};
1297 }
1298
1299 if constexpr (std::is_void_v<func_return_type>) {
1300 std::invoke(func, *std::forward<Exp>(exp));
1301 return result_type();
1302 } else {
1303 return result_type(std::invoke(func, *std::forward<Exp>(exp)));
1304 }
1305 }
1306}
1307
1308} // namespace stdx
1309
1310#endif
Definition: expected.h:896
constexpr expected(const expected &other)
Definition: expected.h:916
E error_type
Definition: expected.h:907
constexpr expected(expected &&other)=default
T value_type
Definition: expected.h:906
constexpr expected(expected &&other) noexcept((std::is_nothrow_move_constructible_v< T >))
Definition: expected.h:928
constexpr expected() noexcept
Definition: expected.h:911
bool has_value_
Definition: expected.h:1267
constexpr expected(const expected &other)=default
Definition: expected.h:284
constexpr expected & operator=(expected &&other)
Definition: expected.h:470
constexpr friend bool operator==(const expected &lhs, const unexpected< E2 > &rhs)
Definition: expected.h:779
constexpr auto or_else(Func &&func) &
Definition: expected.h:815
constexpr auto or_else(Func &&func) &&
Definition: expected.h:820
constexpr auto and_then(Func &&func) &&
Definition: expected.h:796
constexpr expected & operator=(const unexpected< G > &other)
Definition: expected.h:503
constexpr const value_type && value() const &&
Definition: expected.h:671
constexpr T & emplace(std::initializer_list< U > il, Args &&... args) noexcept
Definition: expected.h:558
constexpr auto and_then(Func &&func) const &
Definition: expected.h:801
constexpr auto transform(Func &&func) &
Definition: expected.h:839
constexpr G & rhs
Definition: expected.h:375
constexpr auto transform(Func &&func) const &
Definition: expected.h:849
E error_type
Definition: expected.h:297
constexpr value_type value_or(U &&v) &&
Definition: expected.h:742
constexpr const error_type & error() const &
Definition: expected.h:751
constexpr error_type && error() &&
Definition: expected.h:754
constexpr expected(std::in_place_t, std::initializer_list< U > il, Args &&... args)
Definition: expected.h:430
constexpr const value_type * operator->() const noexcept
Definition: expected.h:687
constexpr bool has_value() const
Definition: expected.h:627
E unex_
Definition: expected.h:883
constexpr const value_type & value() const &
Definition: expected.h:647
constexpr expected(stdx::unexpect_t, std::initializer_list< U > il, Args &&... args)
Definition: expected.h:445
constexpr auto transform(Func &&func) const &&
Definition: expected.h:854
constexpr value_type value_or(U &&v) const &
Definition: expected.h:732
constexpr expected & operator=(U &&val)
Definition: expected.h:488
constexpr expected(expected &&other)=default
constexpr auto or_else(Func &&func) const &&
Definition: expected.h:830
constexpr T & emplace(Args &&... args) noexcept
Definition: expected.h:544
static constexpr bool can_value_convert_construct
Definition: expected.h:351
constexpr auto transform(Func &&func) &&
Definition: expected.h:844
constexpr value_type * operator->() noexcept
Definition: expected.h:694
constexpr ~expected()
Definition: expected.h:534
static constexpr bool can_construct_from_value_type
Definition: expected.h:395
void assign_val(U &&u)
Definition: expected.h:860
T value_type
Definition: expected.h:296
constexpr value_type & value() &
Definition: expected.h:636
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:574
constexpr value_type && value() &&
Definition: expected.h:659
constexpr auto or_else(Func &&func) const &
Definition: expected.h:825
constexpr const value_type && operator*() const &&noexcept
Definition: expected.h:715
static constexpr bool constructor_is_explicit
Definition: expected.h:346
constexpr expected & operator=(unexpected< G > &&other)
Definition: expected.h:516
constexpr expected() noexcept(std::is_nothrow_default_constructible_v< T >)
Definition: expected.h:304
constexpr expected & operator=(expected const &other)
Definition: expected.h:453
constexpr error_type & error() &
Definition: expected.h:753
constexpr expected(stdx::unexpect_t, Args &&... args)
Definition: expected.h:439
constexpr auto and_then(Func &&func) const &&
Definition: expected.h:806
bool has_value_
Definition: expected.h:891
constexpr expected(std::in_place_t, Args &&... args)
Definition: expected.h:424
constexpr const error_type && error() const &&
Definition: expected.h:752
constexpr const value_type & operator*() const &noexcept
Definition: expected.h:701
T val_
Definition: expected.h:882
constexpr auto and_then(Func &&func) &
Definition: expected.h:791
constexpr value_type && operator*() &&noexcept
Definition: expected.h:722
constexpr expected(expected &&other) noexcept((std::is_nothrow_move_constructible_v< E > &&std::is_nothrow_move_constructible_v< T >))
Definition: expected.h:330
constexpr value_type & operator*() &noexcept
Definition: expected.h:708
constexpr expected(const expected &other) noexcept((std::is_nothrow_copy_constructible_v< T > &&std::is_nothrow_copy_constructible_v< E >))
Definition: expected.h:312
constexpr expected(const expected &other)=default
void assign_unex(U &&u)
Definition: expected.h:871
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
error_type error_
Definition: expected.h:184
constexpr const error_type & error() const &noexcept
Definition: expected.h:154
constexpr const error_type && error() const &&noexcept
Definition: expected.h:156
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
constexpr unexpected(std::in_place_t, Args &&... args) noexcept(std::is_nothrow_constructible_v< E, Args... >)
Definition: expected.h:132
constexpr friend void swap(unexpected &lhs, unexpected &rhs) noexcept(noexcept(lhs.swap(rhs)))
Definition: expected.h:178
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:173
error_type
Definition: error.h:36
#define U
Definition: ctype-tis620.cc:74
#define LIKELY(x)
Definition: expected.h:633
void destroy_at(T *ptr)
Definition: my_alloc.h:459
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:927
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:239
constexpr auto or_else_impl(Exp &&exp, Func &&func)
Definition: expected.h:268
constexpr bool is_unexpected
Definition: expected.h:203
constexpr void reinit_expected(NewT *new_val, OldT *old_val, Args &&... args)
Definition: expected.h:209
constexpr bool is_expected
Definition: expected.h:197
Definition: bit.h:32
constexpr auto expected_transform_impl(Exp &&exp, Func &&func)
Definition: expected.h:1271
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:589