MySQL 9.2.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 // (1)
642 constexpr value_type &value() & {
643 static_assert(std::is_copy_constructible_v<E>,
644 "error-type must be copy-constructible");
645 if (has_value()) [[likely]] {
646 return val_;
647 }
648
649 throw bad_expected_access(std::as_const(error()));
650 }
651
652 // (2)
653 constexpr const value_type &value() const & {
654 static_assert(std::is_copy_constructible_v<E>,
655 "error-type must be copy-constructible");
656
657 if (has_value()) [[likely]] {
658 return val_;
659 }
660
661 throw bad_expected_access(std::as_const(error()));
662 }
663
664 // (3)
665 constexpr value_type &&value() && {
666 static_assert(std::is_copy_constructible_v<E> &&
667 std::is_constructible_v<E, decltype(std::move(error()))>);
668
669 if (has_value()) [[likely]] {
670 return std::move(val_);
671 }
672
673 throw bad_expected_access(std::move(error()));
674 }
675
676 // (4)
677 constexpr const value_type &&value() const && {
678 static_assert(std::is_copy_constructible_v<E> &&
679 std::is_constructible_v<E, decltype(std::move(error()))>);
680
681 if (has_value()) [[likely]] {
682 return std::move(val_);
683 }
684
685 throw bad_expected_access(std::move(error()));
686 }
687
688 // unchecked value access
689
690 // (1)
691 constexpr const value_type *operator->() const noexcept {
692 assert(has_value());
693
694 return std::addressof(val_);
695 }
696
697 // (2)
698 constexpr value_type *operator->() noexcept {
699 assert(has_value());
700
701 return std::addressof(val_);
702 }
703
704 // (3)
705 constexpr const value_type &operator*() const &noexcept {
706 assert(has_value());
707
708 return val_;
709 }
710
711 // (4)
712 constexpr value_type &operator*() &noexcept {
713 assert(has_value());
714
715 return val_;
716 }
717
718 // (5)
719 constexpr const value_type &&operator*() const &&noexcept {
720 assert(has_value());
721
722 return std::move(val_);
723 }
724
725 // (6)
726 constexpr value_type &&operator*() &&noexcept {
727 assert(has_value());
728
729 return std::move(val_);
730 }
731
732 // value_or
733
734 // (1)
735 template <class U>
736 constexpr value_type value_or(U &&v) const & {
737 static_assert(
738 std::is_copy_constructible_v<T> && std::is_convertible_v<U &&, T>,
739 "T must be copy-constructible and convertible from U&&");
740
741 return has_value() ? **this : static_cast<T>(std::forward<U>(v));
742 }
743
744 // (2)
745 template <class U>
746 constexpr value_type value_or(U &&v) && {
747 static_assert(
748 std::is_move_constructible_v<T> && std::is_convertible_v<U &&, T>,
749 "T must be move-constructible and convertible from U&&");
750
751 return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v));
752 }
753
754 // error accessors
755 constexpr const error_type &error() const & { return unex_; }
756 constexpr const error_type &&error() const && { return std::move(unex_); }
757 constexpr error_type &error() & { return unex_; }
758 constexpr error_type &&error() && { return std::move(unex_); }
759
760 // operator==
761
762 // (1)
763 template <class T2, class E2>
764 requires(!std::is_void_v<T2>)
765 friend constexpr bool operator==(const expected &lhs,
767 if (lhs.has_value() != rhs.has_value()) return false;
768
769 if (!lhs.has_value()) return lhs.error() == rhs.error();
770 return static_cast<bool>(*lhs == *rhs);
771 }
772
773 // (3)
774 template <class T2>
775 requires(!impl::is_expected<T2>)
776 friend constexpr bool operator==(const expected &lhs, const T2 &rhs) {
777 return lhs.has_value() && static_cast<bool>(*lhs == rhs);
778 }
779
780 // (4)
781 template <class E2>
782 friend constexpr bool operator==(const expected &lhs,
783 const unexpected<E2> &rhs) {
784 if (lhs.has_value()) return false;
785
786 return static_cast<bool>(lhs.error() == rhs.error());
787 }
788
789 //
790 // and_then
791 //
792
793 template <class Func>
794 constexpr auto and_then(Func &&func) & {
795 return base::and_then_impl(*this, std::forward<Func>(func));
796 }
797
798 template <class Func>
799 constexpr auto and_then(Func &&func) && {
800 return base::and_then_impl(std::move(*this), std::forward<Func>(func));
801 }
802
803 template <class Func>
804 constexpr auto and_then(Func &&func) const & {
805 return base::and_then_impl(*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(std::move(*this), std::forward<Func>(func));
811 }
812
813 //
814 // or_else
815 //
816
817 template <class Func>
818 constexpr auto or_else(Func &&func) & {
819 return base::or_else_impl(*this, std::forward<Func>(func));
820 }
821
822 template <class Func>
823 constexpr auto or_else(Func &&func) && {
824 return base::or_else_impl(std::move(*this), std::forward<Func>(func));
825 }
826
827 template <class Func>
828 constexpr auto or_else(Func &&func) const & {
829 return base::or_else_impl(*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(std::move(*this), std::forward<Func>(func));
835 }
836
837 //
838 // transform
839 //
840
841 template <class Func>
842 constexpr auto transform(Func &&func) & {
843 return expected_transform_impl(*this, std::forward<Func>(func));
844 }
845
846 template <class Func>
847 constexpr auto transform(Func &&func) && {
848 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
849 }
850
851 template <class Func>
852 constexpr auto transform(Func &&func) const & {
853 return expected_transform_impl(*this, std::forward<Func>(func));
854 }
855
856 template <class Func>
857 constexpr auto transform(Func &&func) const && {
858 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
859 }
860
861 private:
862 template <class U>
863 void assign_val(U &&u) {
864 if (has_value_) {
865 val_ = std::forward<U>(u);
866 } else {
867 impl::reinit_expected(std::addressof(val_), std::addressof(unex_),
868 std::forward<U>(u));
869 has_value_ = true;
870 }
871 }
872
873 template <class U>
874 void assign_unex(U &&u) {
875 if (has_value_) {
876 impl::reinit_expected(std::addressof(unex_), std::addressof(val_),
877 std::forward<U>(u));
878 has_value_ = false;
879 } else {
880 unex_ = std::forward<U>(u);
881 }
882 }
883
884 union {
887#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 12
888 // workaround GCC 10/11's "maybe-uninitialized"
889 // GCC 12 and 13 do not report it.
890 volatile char gcc_pr80635_workaround_maybe_uninitialized_;
891#endif
892 };
893
895};
896
897template <class T, class E>
898 requires(std::is_void_v<T>)
900 public:
901 static_assert(!std::is_void_v<E>, "E must not be void");
902 static_assert(!std::is_reference_v<T>, "T must not be a reference");
903 static_assert(!std::is_same_v<T, std::remove_cv<std::in_place_t>>,
904 "T must not be std::in_place_t");
905 static_assert(!std::is_same_v<T, std::remove_cv<unexpected<E>>>,
906 "T must not be unexpected<E>");
907 static_assert(!std::is_reference_v<E>, "E must not be a reference");
908
909 using value_type = T;
910 using error_type = E;
912
913 // (1)
914 constexpr expected() noexcept : dummy_(), has_value_(true) {}
915
916 // (2)
917 constexpr expected(const expected &other) = default;
918
919 constexpr expected(const expected &other)
920 requires((std::is_copy_constructible_v<E> &&
921 !std::is_trivially_copy_constructible_v<E>))
922 : dummy_(), has_value_{other.has_value()} {
923 if (!has_value()) {
924 std::construct_at(std::addressof(unex_), other.unex_);
925 }
926 }
927
928 // (3)
929 constexpr expected(expected &&other) = default;
930
931 constexpr expected(expected &&other) //
932 noexcept((std::is_nothrow_move_constructible_v<T>))
933 requires((std::is_move_constructible_v<E> &&
934 !std::is_trivially_move_constructible_v<E>))
935 : dummy_(), has_value_{other.has_value()} {
936 if (!has_value()) {
937 std::construct_at(std::addressof(unex_), std::move(other.unex_));
938 }
939 }
940
941 template <class UF, class GF>
942 static constexpr bool constructor_is_explicit =
943 (!std::is_convertible_v<UF, T> || !std::is_convertible_v<GF, E>);
944
945 template <class U, class G, class UF, class GF>
946 static constexpr bool can_value_convert_construct =
947 (std::is_void_v<U> && std::is_constructible_v<E, GF> &&
948 !std::is_constructible_v<unexpected<E>, expected<U, G> &> &&
949 !std::is_constructible_v<unexpected<E>, expected<U, G>> &&
950 !std::is_constructible_v<unexpected<E>, const expected<U, G> &> &&
951 !std::is_constructible_v<unexpected<E>, const expected<U, G>>);
952
953 // (4)
954 template <class U, class G, class UF = std::add_lvalue_reference_t<const U>,
955 class GF = const G &>
956 constexpr explicit(constructor_is_explicit<UF, GF>)
958 requires can_value_convert_construct<U, G, UF, GF>
959 : dummy_(), has_value_{rhs.has_value()} {
960 if (!rhs.has_value()) {
961 std::construct_at(std::addressof(unex_), rhs.error());
962 }
963 }
964
965 // (5)
966 template <class U, class G, class UF = U, class GF = G>
967 constexpr explicit(constructor_is_explicit<UF, GF>) //
968 expected(expected<U, G> &&rhs) //
969 requires can_value_convert_construct<U, G, UF, GF>
970 : dummy_(), has_value_{rhs.has_value()} {
971 if (!rhs.has_value()) {
972 std::construct_at(std::addressof(unex_), std::move(rhs.error()));
973 }
974 }
975
976 // (6) requires T is not cv void.
977
978 // (7)
979 template <class G>
980 constexpr explicit(!std::is_convertible_v<const G &, E>)
981 expected(const unexpected<G> &err)
982 requires std::is_constructible_v<E, const G &>
983 : unex_(err.error()), has_value_{false} {}
984
985 // (8)
986 template <class G>
987 constexpr explicit(!std::is_convertible_v<G, E>) //
988 expected(unexpected<G> &&err)
989 requires std::is_constructible_v<E, G>
990 : unex_(std::move(err.error())), has_value_{false} {}
991
992 // (9) requires T is not cv void.
993
994 // (10) requires T is not cv void.
995
996 // (11)
997 template <class... Args>
998 constexpr explicit expected(std::in_place_t) : has_value_{true} {}
999
1000 // (12)
1001 template <class... Args>
1002 constexpr explicit expected(stdx::unexpect_t, Args &&...args)
1003 requires std::is_constructible_v<E, Args...>
1004 : unex_(std::forward<Args>(args)...), has_value_{false} {}
1005
1006 // (13)
1007 template <class U, class... Args>
1008 constexpr explicit expected(stdx::unexpect_t, std::initializer_list<U> il,
1009 Args &&...args) //
1010 requires std::is_constructible_v<E, std::initializer_list<U> &, Args...>
1011 : unex_(il, std::forward<Args>(args)...), has_value_{false} {}
1012
1013 // assignment
1014
1015 // (1)
1016 constexpr expected &operator=(expected const &other)
1017 requires((std::is_copy_assignable_v<E> && //
1018 std::is_copy_constructible_v<E>))
1019 {
1020 if (other.has_value()) {
1021 emplace(); // destroys unex_ and sets has_value_ = true
1022 } else {
1023 assign_unex(other.unex_);
1024 }
1025
1026 return *this;
1027 }
1028
1029 // (2)
1030 constexpr expected &operator=(expected &&other)
1031 requires((std::is_move_assignable_v<E> && //
1032 std::is_move_constructible_v<E>))
1033 {
1034 if (other.has_value()) {
1035 emplace();
1036 } else {
1037 assign_unex(other.unex_);
1038 }
1039 return *this;
1040 }
1041
1042 // (3) requires T is not cv void.
1043
1044 // (4)
1045 template <class G, class GF = const G &>
1046 constexpr expected &operator=(const unexpected<G> &other)
1047 requires((std::is_constructible_v<E, GF> && //
1048 std::is_assignable_v<E &, GF>))
1049 {
1050 assign_unex(other.error());
1051
1052 return *this;
1053 }
1054
1055 // (5)
1056 template <class G, class GF = G>
1057 constexpr expected &operator=(unexpected<G> &&other)
1058 requires(std::is_constructible_v<E, GF> && //
1059 std::is_assignable_v<E &, GF>)
1060 {
1061 assign_unex(std::move(other.error()));
1062
1063 return *this;
1064 }
1065
1066 // destruct
1067#if defined(CXX_HAS_CONDITIONAL_TRIVIAL_DESTRUCTOR)
1068 constexpr ~expected()
1069 requires((std::is_trivially_destructible_v<E>))
1070 = default;
1071#endif
1072
1073 constexpr ~expected() {
1074 if (!has_value()) {
1075 std::destroy_at(std::addressof(unex_));
1076 }
1077 }
1078
1079 // emplace
1080 constexpr void emplace() noexcept {
1081 if (!has_value()) {
1082 std::destroy_at(std::addressof(unex_));
1083 has_value_ = true;
1084 }
1085 }
1086
1087 // swap
1088 constexpr void swap(expected &other) //
1089 noexcept((std::is_nothrow_move_constructible_v<E> && //
1090 std::is_nothrow_swappable_v<E>))
1091 requires((std::is_swappable_v<E> && //
1092 std::is_move_constructible_v<E>)) //
1093 {
1094 using std::swap;
1095
1096 if (bool(*this) && bool(other)) {
1097 // is void
1098 } else if (!bool(*this) && !bool(other)) {
1099 swap(unex_, other.unex_);
1100 } else if (bool(*this) && !bool(other)) {
1101 std::construct_at(std::addressof(unex_), std::move(other.unex_));
1102 std::destroy_at(std::addressof(other.unex_));
1103
1104 swap(has_value_, other.has_value_);
1105 } else if (!bool(*this) && bool(other)) {
1106 other.swap(*this);
1107 }
1108 }
1109
1110 constexpr bool has_value() const { return has_value_; }
1111 constexpr explicit operator bool() const noexcept { return has_value(); }
1112
1113 // value accessors
1114
1115 constexpr void value() const & {
1116 static_assert(std::is_copy_constructible_v<E>);
1117
1118 if (!has_value()) {
1119 throw bad_expected_access(std::as_const(error()));
1120 }
1121 }
1122
1123 constexpr void value() && {
1124 static_assert(std::is_move_constructible_v<E>);
1125
1126 if (!has_value()) {
1127 throw bad_expected_access(std::as_const(error()));
1128 }
1129 }
1130
1131 // unchecked value access
1132
1133 // (3)
1134 constexpr void operator*() const noexcept { assert(has_value()); }
1135
1136 template <class U>
1137 constexpr value_type value_or(U &&v) const & {
1138 static_assert(
1139 std::is_copy_constructible_v<T> && std::is_convertible_v<U &&, T>,
1140 "T must be copy-constructible and convertible from U&&");
1141
1142 return has_value() ? **this : static_cast<T>(std::forward<U>(v));
1143 }
1144
1145 template <class U>
1146 constexpr value_type value_or(U &&v) && {
1147 static_assert(
1148 std::is_move_constructible_v<T> && std::is_convertible_v<U &&, T>,
1149 "T must be move-constructible and convertible from U&&");
1150
1151 return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v));
1152 }
1153
1154 // error accessors
1155 constexpr const error_type &error() const & { return unex_; }
1156 constexpr const error_type &&error() const && { return std::move(unex_); }
1157 constexpr error_type &error() & { return unex_; }
1158 constexpr error_type &&error() && { return std::move(unex_); }
1159
1160 // operator==
1161
1162 // (1) requires T is not cv void
1163
1164 // (2)
1165 template <class T2, class E2>
1166 friend constexpr bool operator==(const expected &lhs,
1167 const stdx::expected<T2, E2> &rhs)
1168 requires(std::is_void_v<T2>)
1169 {
1170 if (lhs.has_value() != rhs.has_value()) return false;
1171
1172 if (lhs.has_value()) return true;
1173
1174 return lhs.error() == rhs.error();
1175 }
1176
1177 // (3) requires T is not cv void
1178
1179 // (4)
1180 template <class E2>
1181 friend constexpr bool operator==(const expected &lhs,
1182 const unexpected<E2> &rhs) {
1183 if (lhs.has_value()) return false;
1184
1185 return static_cast<bool>(lhs.error() == rhs.error());
1186 }
1187 //
1188 // and_then
1189 //
1190
1191 template <class Func>
1192 constexpr auto and_then(Func &&func) & {
1193 return base::and_then_impl(*this, std::forward<Func>(func));
1194 }
1195
1196 template <class Func>
1197 constexpr auto and_then(Func &&func) && {
1198 return base::and_then_impl(std::move(*this), std::forward<Func>(func));
1199 }
1200
1201 template <class Func>
1202 constexpr auto and_then(Func &&func) const & {
1203 return base::and_then_impl(*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(std::move(*this), std::forward<Func>(func));
1209 }
1210
1211 //
1212 // or_else
1213 //
1214
1215 template <class Func>
1216 constexpr auto or_else(Func &&func) & {
1217 return base::or_else_impl(*this, std::forward<Func>(func));
1218 }
1219
1220 template <class Func>
1221 constexpr auto or_else(Func &&func) && {
1222 return base::or_else_impl(std::move(*this), std::forward<Func>(func));
1223 }
1224
1225 template <class Func>
1226 constexpr auto or_else(Func &&func) const & {
1227 return base::or_else_impl(*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(std::move(*this), std::forward<Func>(func));
1233 }
1234
1235 //
1236 // transform
1237 //
1238
1239 template <class Func>
1240 constexpr auto transform(Func &&func) & {
1241 return expected_transform_impl(*this, std::forward<Func>(func));
1242 }
1243
1244 template <class Func>
1245 constexpr auto transform(Func &&func) && {
1246 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
1247 }
1248
1249 template <class Func>
1250 constexpr auto transform(Func &&func) const & {
1251 return expected_transform_impl(*this, std::forward<Func>(func));
1252 }
1253
1254 template <class Func>
1255 constexpr auto transform(Func &&func) const && {
1256 return expected_transform_impl(std::move(*this), std::forward<Func>(func));
1257 }
1258
1259 private:
1260 template <class U>
1261 void assign_unex(U &&u) {
1262 if (has_value_) {
1263 std::construct_at(std::addressof(unex_), std::forward<U>(u));
1264 has_value_ = false;
1265 } else {
1266 unex_ = std::forward<U>(u);
1267 }
1268 }
1269
1270 struct S {};
1271
1272 union {
1275 };
1276
1278};
1279
1280template <class Exp, class Func>
1281constexpr auto expected_transform_impl(Exp &&exp, Func &&func) {
1282 // type of the value that's passed to func
1283 using func_value_type = typename std::decay_t<Exp>::value_type;
1284
1285 if constexpr (std::is_void_v<func_value_type>) {
1286 using func_return_type = std::invoke_result_t<Func>;
1287 using result_type =
1289
1290 if (!exp.has_value()) {
1291 return result_type{stdx::unexpect, std::forward<Exp>(exp).error()};
1292 }
1293
1294 if constexpr (std::is_void_v<func_return_type>) {
1295 std::invoke(func);
1296 return result_type();
1297 } else {
1298 return result_type(std::invoke(func));
1299 }
1300 } else {
1301 using func_return_type = std::invoke_result_t<Func, func_value_type>;
1302 using result_type =
1304
1305 if (!exp.has_value()) {
1306 return result_type{stdx::unexpect, std::forward<Exp>(exp).error()};
1307 }
1308
1309 if constexpr (std::is_void_v<func_return_type>) {
1310 std::invoke(func, *std::forward<Exp>(exp));
1311 return result_type();
1312 } else {
1313 return result_type(std::invoke(func, *std::forward<Exp>(exp)));
1314 }
1315 }
1316}
1317
1318} // namespace stdx
1319
1320#endif
Definition: expected.h:899
E error_type
Definition: expected.h:910
E unex_
Definition: expected.h:1274
constexpr expected(expected &&other)=default
S dummy_
Definition: expected.h:1273
T value_type
Definition: expected.h:909
constexpr expected(expected &&other) noexcept((std::is_nothrow_move_constructible_v< T >))
Definition: expected.h:931
constexpr expected() noexcept
Definition: expected.h:914
constexpr expected(const expected &other)
Definition: expected.h:919
bool has_value_
Definition: expected.h:1277
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:782
constexpr T & emplace(Args &&...args) noexcept
Definition: expected.h:551
constexpr auto or_else(Func &&func) &
Definition: expected.h:818
constexpr auto or_else(Func &&func) &&
Definition: expected.h:823
constexpr auto and_then(Func &&func) &&
Definition: expected.h:799
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:677
constexpr auto and_then(Func &&func) const &
Definition: expected.h:804
constexpr auto transform(Func &&func) &
Definition: expected.h:842
constexpr G & rhs
Definition: expected.h:377
constexpr auto transform(Func &&func) const &
Definition: expected.h:852
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:746
constexpr const error_type & error() const &
Definition: expected.h:755
constexpr error_type && error() &&
Definition: expected.h:758
constexpr const value_type * operator->() const noexcept
Definition: expected.h:691
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:886
constexpr const value_type & value() const &
Definition: expected.h:653
constexpr auto transform(Func &&func) const &&
Definition: expected.h:857
constexpr value_type value_or(U &&v) const &
Definition: expected.h:736
constexpr expected & operator=(U &&val)
Definition: expected.h:491
constexpr expected(expected &&other)=default
constexpr auto or_else(Func &&func) const &&
Definition: expected.h:833
static constexpr bool can_value_convert_construct
Definition: expected.h:353
constexpr auto transform(Func &&func) &&
Definition: expected.h:847
constexpr value_type * operator->() noexcept
Definition: expected.h:698
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:863
T value_type
Definition: expected.h:298
constexpr value_type & value() &
Definition: expected.h:642
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:665
constexpr auto or_else(Func &&func) const &
Definition: expected.h:828
constexpr const value_type && operator*() const &&noexcept
Definition: expected.h:719
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:757
constexpr auto and_then(Func &&func) const &&
Definition: expected.h:809
bool has_value_
Definition: expected.h:894
constexpr const error_type && error() const &&
Definition: expected.h:756
constexpr const value_type & operator*() const &noexcept
Definition: expected.h:705
T val_
Definition: expected.h:885
constexpr auto and_then(Func &&func) &
Definition: expected.h:794
constexpr value_type && operator*() &&noexcept
Definition: expected.h:726
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:712
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:874
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
void destroy_at(T *ptr)
Definition: my_alloc.h:462
Header for compiler-dependent features.
constexpr bool likely(bool expr)
Definition: my_compiler.h:57
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:1281
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