cpp_result e4f6bfe
Loading...
Searching...
No Matches
result.hpp
Go to the documentation of this file.
1// clang-format off
107// result.hpp - Rust-like Result<T, E> for C++17
108// SPDX-License-Identifier: MIT
109//
110// This header provides a modern, ergonomic Result type for C++17 inspired by
111// Rust. It supports combinators, helpers, and void specialization.
112//
113// All API is in the cpp_result namespace.
114//
115// --- API OVERVIEW ---
116//
117// Construction:
118// Result<T, E>::Ok(T)
119// Result<T, E>::Err(E)
120// Result<void, E>::Ok()
121// Result<void, E>::Err(E)
122// cpp_result::Ok<T, E>(T)
123// cpp_result::Err<T, E>(E)
124// cpp_result::Ok<E>()
125// cpp_result::Err<E>(E)
126//
127// Query:
128// is_ok(), is_err()
129//
130// Unwrap:
131// unwrap(), unwrap_err(), unwrap_or(value), unwrap_or_else(fn)
132// expect(msg), expect_err(msg)
133//
134// Combinators:
135// map(fn), map_err(fn), and_then(fn)
136// inspect(fn), inspect_err(fn)
137//
138// See the documentation below each function for usage examples.
139// clang-format on
140
141#pragma once
142
143#ifndef CPP_RESULT_HAS_STATEMENT_EXPR
144#if defined(__GNUC__) || defined(__clang__)
145#define CPP_RESULT_HAS_STATEMENT_EXPR 1
146#else
147#define CPP_RESULT_HAS_STATEMENT_EXPR 0
148#endif
149#endif
150
151#ifndef CPP_RESULT_FEATURE_ALL
152#define CPP_RESULT_FEATURE_ALL 1
153#endif
154#ifndef CPP_RESULT_FEATURE_UNWRAP
155#define CPP_RESULT_FEATURE_UNWRAP CPP_RESULT_FEATURE_ALL
156#endif
157#ifndef CPP_RESULT_FEATURE_MAP
158#define CPP_RESULT_FEATURE_MAP CPP_RESULT_FEATURE_ALL
159#endif
160#ifndef CPP_RESULT_FEATURE_ANDOR
161#define CPP_RESULT_FEATURE_ANDOR CPP_RESULT_FEATURE_ALL
162#endif
163#ifndef CPP_RESULT_FEATURE_INSPECT
164#define CPP_RESULT_FEATURE_INSPECT CPP_RESULT_FEATURE_ALL
165#endif
166#ifndef CPP_RESULT_FEATURE_CONTAINS
167#define CPP_RESULT_FEATURE_CONTAINS CPP_RESULT_FEATURE_ALL
168#endif
169#ifndef CPP_RESULT_FEATURE_FLATTEN
170#define CPP_RESULT_FEATURE_FLATTEN CPP_RESULT_FEATURE_ALL
171#endif
172#ifndef CPP_RESULT_FEATURE_OPTIONAL
173#define CPP_RESULT_FEATURE_OPTIONAL CPP_RESULT_FEATURE_ALL
174#endif
175
176// clang-format off
196// clang-format on
197#if CPP_RESULT_HAS_STATEMENT_EXPR
198#define TRY(expr) \
199 ({ \
200 auto &&__res = (expr); \
201 using __res_type = std::decay_t<decltype(__res)>; \
202 if (__res.is_err()) \
203 return __res_type::Err(__res.unwrap_err()); \
204 std::move(__res.unwrap()); \
205 })
206#endif
207
208// clang-format off
226// clang-format on
227#define TRY_ASSIGN(name, expr) \
228 auto &&__res_##name = (expr); \
229 using __res_type_##name = std::decay_t<decltype(__res_##name)>; \
230 if (__res_##name.is_err()) \
231 return __res_type_##name::Err(__res_##name.unwrap_err()); \
232 auto &name = __res_##name.unwrap()
233
234#include <cstdio>
235#include <cstdlib>
236#if CPP_RESULT_FEATURE_OPTIONAL
237#include <optional>
238#endif // CPP_RESULT_FEATURE_OPTIONAL
239#include <type_traits>
240#include <utility>
241
242#define EXPECT_OR_ABORT(cond, msg) \
243 do { \
244 if (!(cond)) { \
245 std::fputs(msg, stderr); \
246 std::fputc('\n', stderr); \
247 std::abort(); \
248 } \
249 } while (0)
250
251namespace cpp_result {
252
266template <typename T, typename E> class [[nodiscard]] Result {
267 static_assert(!std::is_reference_v<T> && !std::is_reference_v<E>,
268 "Result<T,E> does not support reference types");
269
270public:
282 static inline Result Ok(T val) noexcept { return Result(std::move(val)); }
283
295 static inline Result Err(E err) noexcept { return Result(std::move(err)); }
296
304 constexpr bool is_ok() const noexcept { return is_ok_; }
305
313 constexpr bool is_err() const noexcept { return !is_ok_; }
314
315#if CPP_RESULT_FEATURE_UNWRAP
324 inline T &unwrap() noexcept {
325 EXPECT_OR_ABORT(is_ok_, "unwrap called on Result::Err()");
326 return data_.value;
327 }
328 inline const T &unwrap() const noexcept {
329 EXPECT_OR_ABORT(is_ok_, "unwrap called on Result::Err()");
330 return data_.value;
331 }
332
341 inline E &unwrap_err() noexcept {
342 EXPECT_OR_ABORT(!is_ok_, "unwrap_err called on Result::Ok()");
343 return data_.error;
344 }
345 inline const E &unwrap_err() const noexcept {
346 EXPECT_OR_ABORT(!is_ok_, "unwrap_err called on Result::Ok()");
347 return data_.error;
348 }
349
358 inline T unwrap_or(T default_value) const noexcept {
359 return is_ok_ ? data_.value : default_value;
360 }
361
370 template <typename F>
371 inline T unwrap_or_else(F &&func) const noexcept(noexcept(func())) {
372 return is_ok_ ? data_.value : std::forward<F>(func)();
373 }
374
386 noexcept(std::is_nothrow_default_constructible_v<T>) {
387 if (is_ok_)
388 return data_.value;
389 return T{};
390 }
391
399 T &expect(const char *msg) noexcept {
400 EXPECT_OR_ABORT(is_ok_, msg);
401 return data_.value;
402 }
403 const T &expect(const char *msg) const noexcept {
404 EXPECT_OR_ABORT(is_ok_, msg);
405 return data_.value;
406 }
407
415 E &expect_err(const char *msg) noexcept {
416 EXPECT_OR_ABORT(!is_ok_, msg);
417 return data_.error;
418 }
419 const E &expect_err(const char *msg) const noexcept {
420 EXPECT_OR_ABORT(!is_ok_, msg);
421 return data_.error;
422 }
423
433 template <typename Pred>
434 bool is_ok_and(Pred &&pred) const
435 noexcept(noexcept(pred(std::declval<T>()))) {
436 return is_ok_ && pred(data_.value);
437 }
438
448 template <typename Pred>
449 bool is_err_and(Pred &&pred) const
450 noexcept(noexcept(pred(std::declval<E>()))) {
451 return !is_ok_ && pred(data_.error);
452 }
453#endif // CPP_RESULT_FEATURE_UNWRAP
454
455#if CPP_RESULT_FEATURE_MAP
464 template <typename F, typename U = std::invoke_result_t<F, T>>
465 Result<U, E> map(F &&func) const noexcept(noexcept(func(std::declval<T>()))) {
466 if (is_ok_)
467 return Result<U, E>::Ok(func(data_.value));
468 return Result<U, E>::Err(data_.error);
469 }
470
479 template <typename F, typename E2 = std::invoke_result_t<F, E>>
480 Result<T, E2> map_err(F &&func) const
481 noexcept(noexcept(func(std::declval<E>()))) {
482 if (is_ok_)
483 return Result<T, E2>::Ok(data_.value);
484 return Result<T, E2>::Err(func(data_.error));
485 }
486
494 template <typename U, typename F> U map_or(U default_value, F &&func) const {
495 return is_ok_ ? func(data_.value) : default_value;
496 }
497
507 template <typename D, typename F>
508 auto map_or_else(D &&default_fn, F &&func) const {
509 return is_ok_ ? func(data_.value) : default_fn();
510 }
511#endif // CPP_RESULT_FEATURE_MAP
512
513#if CPP_RESULT_FEATURE_ANDOR
524 template <typename F, typename R = typename std::invoke_result_t<F, T>>
525 R and_then(F &&func) const noexcept(noexcept(func(std::declval<T>()))) {
526 if (is_ok_)
527 return func(data_.value);
528 return R::Err(data_.error);
529 }
530
539 template <typename R2> auto and_(R2 &&res) const {
540 if (is_ok_)
541 return std::forward<R2>(res);
542 return Result<T, E>::Err(data_.error);
543 }
544
553 template <typename R2> auto or_(R2 &&res) const {
554 if (!is_ok_)
555 return std::forward<R2>(res);
556 return *this;
557 }
558
566 template <typename F> auto or_else(F &&op) const {
567 if (!is_ok_)
568 return op();
569 return *this;
570 }
571#endif // CPP_RESULT_FEATURE_ANDOR
572
573#if CPP_RESULT_FEATURE_INSPECT
581 template <typename F>
582 const Result &inspect(F &&func) const
583 noexcept(noexcept(func(std::declval<const T &>()))) {
584 if (is_ok_)
585 func(data_.value);
586 return *this;
587 }
588
596 template <typename F>
597 const Result &inspect_err(F &&func) const
598 noexcept(noexcept(func(std::declval<const E &>()))) {
599 if (!is_ok_)
600 func(data_.error);
601 return *this;
602 }
603#endif // CPP_RESULT_FEATURE_INSPECT
604
605#if CPP_RESULT_FEATURE_CONTAINS
613 bool contains(const T &value) const { return is_ok_ && data_.value == value; }
614
622 bool contains_err(const E &error) const {
623 return !is_ok_ && data_.error == error;
624 }
625#endif // CPP_RESULT_FEATURE_CONTAINS
626
627#if CPP_RESULT_FEATURE_FLATTEN
636 auto flatten() const {
637 using Inner = decltype(data_.value);
638 if (is_ok_)
639 return data_.value;
640 return Inner::Err(data_.error);
641 }
642#endif // CPP_RESULT_FEATURE_FLATTEN
643
644#if CPP_RESULT_FEATURE_OPTIONAL
653 std::optional<T> ok() const {
654 return is_ok_ ? std::optional<T>(data_.value) : std::nullopt;
655 }
656
665 std::optional<E> err() const {
666 return !is_ok_ ? std::optional<E>(data_.error) : std::nullopt;
667 }
668#endif
669
670 ~Result() { destroy(); }
671
672 // Move semantics
673 Result(Result &&other) noexcept(std::is_nothrow_move_constructible_v<T> &&
674 std::is_nothrow_move_constructible_v<E>)
675 : is_ok_(other.is_ok_) {
676 if (is_ok_)
677 new (&data_.value) T(std::move(other.data_.value));
678 else
679 new (&data_.error) E(std::move(other.data_.error));
680 }
681
682 Result &
683 operator=(Result &&other) noexcept(std::is_nothrow_move_assignable_v<T> &&
684 std::is_nothrow_move_assignable_v<E>) {
685 if (this != &other) {
686 destroy();
687 is_ok_ = other.is_ok_;
688 if (is_ok_)
689 new (&data_.value) T(std::move(other.data_.value));
690 else
691 new (&data_.error) E(std::move(other.data_.error));
692 }
693 return *this;
694 }
695
696 // Conditional copy semantics
697 Result(const Result &other) noexcept(
698 std::is_nothrow_copy_constructible_v<T> &&
699 std::is_nothrow_copy_constructible_v<E>)
700 : is_ok_(other.is_ok_) {
701 if (is_ok_)
702 new (&data_.value) T(other.data_.value);
703 else
704 new (&data_.error) E(other.data_.error);
705 }
706
707 Result &operator=(const Result &other) noexcept(
708 std::is_nothrow_copy_assignable_v<T> &&
709 std::is_nothrow_copy_assignable_v<E>) {
710 if (this != &other) {
711 destroy();
712 is_ok_ = other.is_ok_;
713 if (is_ok_)
714 new (&data_.value) T(other.data_.value);
715 else
716 new (&data_.error) E(other.data_.error);
717 }
718 return *this;
719 }
720
721private:
722 union Data {
723 T value;
724 E error;
725 Data() {}
726 ~Data() {}
727 } data_;
728 bool is_ok_;
729
730 explicit Result(T val) noexcept : is_ok_(true) {
731 new (&data_.value) T(std::move(val));
732 }
733
734 explicit Result(E err) noexcept : is_ok_(false) {
735 new (&data_.error) E(std::move(err));
736 }
737
738 void destroy() noexcept { is_ok_ ? data_.value.~T() : data_.error.~E(); }
739};
740
756template <typename E> class [[nodiscard]] Result<void, E> {
757 static_assert(!std::is_reference_v<E>,
758 "Result<void,E> does not support reference types");
759
760public:
768 static inline Result Ok() noexcept { return Result(); }
769
778 static inline Result Err(E err) noexcept { return Result(std::move(err)); }
779
787 inline bool is_ok() const noexcept { return is_ok_; }
788
796 inline bool is_err() const noexcept { return !is_ok_; }
797
805 inline void unwrap() noexcept {
806 EXPECT_OR_ABORT(is_ok_, "unwrap called on Result::Err()");
807 }
808
817 inline E &unwrap_err() noexcept {
818 EXPECT_OR_ABORT(!is_ok_, "unwrap_err called on Result::Ok()");
819 return error_;
820 }
821 inline const E &unwrap_err() const noexcept {
822 EXPECT_OR_ABORT(!is_ok_, "unwrap_err called on Result::Ok()");
823 return error_;
824 }
825
834 template <typename F, typename U = std::invoke_result_t<F>>
835 Result<U, E> map(F &&func) const noexcept(noexcept(func())) {
836 if (is_ok_)
837 return Result<U, E>::Ok(func());
838 return Result<U, E>::Err(error_);
839 }
840
849 template <typename F, typename E2 = std::invoke_result_t<F, E>>
850 Result<void, E2> map_err(F &&func) const
851 noexcept(noexcept(func(std::declval<E>()))) {
852 if (is_ok_)
853 return Result<void, E2>::Ok();
854 return Result<void, E2>::Err(func(error_));
855 }
856
868 template <typename F, typename R = std::invoke_result_t<F>>
869 R and_then(F &&func) const noexcept(noexcept(func())) {
870 if (is_ok_)
871 return func();
872 return R::Err(error_);
873 }
874
882 void expect(const char msg[]) const noexcept { EXPECT_OR_ABORT(is_ok_, msg); }
883
891 E &expect_err(const char msg[]) noexcept {
892 EXPECT_OR_ABORT(!is_ok_, msg);
893 return error_;
894 }
895
896 const E &expect_err(const char msg[]) const noexcept {
897 EXPECT_OR_ABORT(!is_ok_, msg);
898 return error_;
899 }
900
908 template <typename F>
909 const Result &inspect(F &&func) const noexcept(noexcept(func())) {
910 if (is_ok_)
911 func();
912 return *this;
913 }
914
922 template <typename F>
923 const Result &inspect_err(F &&func) const
924 noexcept(noexcept(func(std::declval<const E &>()))) {
925 if (!is_ok_)
926 func(error_);
927 return *this;
928 }
929
939 template <typename Pred>
940 bool is_err_and(Pred &&pred) const
941 noexcept(noexcept(pred(std::declval<E>()))) {
942 return !is_ok_ && pred(error_);
943 }
944
955 std::optional<E> err() const {
956 if (!is_ok_)
957 return error_;
958 return std::nullopt;
959 }
960
970 template <typename R2> auto and_(R2 &&res) const {
971 if (is_ok_)
972 return std::forward<R2>(res);
973 return Result<void, E>::Err(error_);
974 }
975
985 template <typename R2> auto or_(R2 &&res) const {
986 if (!is_ok_)
987 return std::forward<R2>(res);
988 return *this;
989 }
990
999 template <typename U, typename F> U map_or(U default_value, F &&func) const {
1000 return is_ok_ ? func() : default_value;
1001 }
1002
1012 template <typename D, typename F>
1013 auto map_or_else(D &&default_fn, F &&func) const {
1014 return is_ok_ ? func() : default_fn();
1015 }
1016
1024 bool contains_err(const E &error) const { return !is_ok_ && error_ == error; }
1025
1026 // Move semantics
1027 Result(Result &&other) noexcept(std::is_nothrow_move_constructible_v<E>)
1028 : is_ok_(other.is_ok_) {
1029 if (!is_ok_)
1030 new (&error_) E(std::move(other.error_));
1031 }
1032
1033 Result &
1034 operator=(Result &&other) noexcept(std::is_nothrow_move_assignable_v<E>) {
1035 if (this != &other) {
1036 is_ok_ = other.is_ok_;
1037 if (!is_ok_)
1038 new (&error_) E(std::move(other.error_));
1039 }
1040 return *this;
1041 }
1042
1043 // Conditional copy semantics
1044 Result(const Result &other) noexcept(std::is_nothrow_copy_constructible_v<E>)
1045 : is_ok_(other.is_ok_) {
1046 if (!is_ok_)
1047 new (&error_) E(other.error_);
1048 }
1049
1050 Result &operator=(const Result &other) noexcept(
1051 std::is_nothrow_copy_assignable_v<E>) {
1052 if (this != &other) {
1053 is_ok_ = other.is_ok_;
1054 if (!is_ok_)
1055 new (&error_) E(other.error_);
1056 }
1057 return *this;
1058 }
1059
1060private:
1061 E error_;
1062 bool is_ok_;
1063
1064 Result() noexcept : is_ok_(true) {}
1065 explicit Result(E err) noexcept : is_ok_(false) {
1066 new (&error_) E(std::move(err));
1067 }
1068};
1069
1070template <typename T, typename E> inline Result<T, E> Ok(T val) {
1071 return Result<T, E>::Ok(std::move(val));
1072}
1073template <typename T, typename E> inline Result<T, E> Err(E err) {
1074 return Result<T, E>::Err(std::move(err));
1075}
1076template <typename E> inline Result<void, E> Ok() {
1077 return Result<void, E>::Ok();
1078}
1079template <typename E> inline Result<void, E> Err(E err) {
1080 return Result<void, E>::Err(std::move(err));
1081}
1082
1083} // namespace cpp_result
Result(const Result &other) noexcept(std::is_nothrow_copy_constructible_v< E >)
Definition result.hpp:1044
bool contains_err(const E &error) const
Returns true if the result is Err and contains the given error.
Definition result.hpp:1024
bool is_err() const noexcept
Returns true if the result is Err.
Definition result.hpp:796
const E & unwrap_err() const noexcept
Definition result.hpp:821
Result & operator=(Result &&other) noexcept(std::is_nothrow_move_assignable_v< E >)
Definition result.hpp:1034
Result< U, E > map(F &&func) const noexcept(noexcept(func()))
Returns unit type if Ok, else returns error.
Definition result.hpp:835
bool is_err_and(Pred &&pred) const noexcept(noexcept(pred(std::declval< E >())))
Returns true if the result is Err and the predicate returns true for the error.
Definition result.hpp:940
bool is_ok() const noexcept
Returns true if the result is Ok.
Definition result.hpp:787
auto and_(R2 &&res) const
Returns res if the result is Ok, otherwise returns self.
Definition result.hpp:970
E & expect_err(const char msg[]) noexcept
Unwraps the error or aborts with a custom message if Ok.
Definition result.hpp:891
Result(Result &&other) noexcept(std::is_nothrow_move_constructible_v< E >)
Definition result.hpp:1027
const E & expect_err(const char msg[]) const noexcept
Definition result.hpp:896
const Result & inspect_err(F &&func) const noexcept(noexcept(func(std::declval< const E & >())))
Calls func(error) if Err, returns self.
Definition result.hpp:923
R and_then(F &&func) const noexcept(noexcept(func()))
Chains another result-producing function if Ok, else propagates Err.
Definition result.hpp:869
U map_or(U default_value, F &&func) const
Applies a function if Ok, else returns default_value.
Definition result.hpp:999
std::optional< E > err() const
Converts the Result into a std::optional<E> (Err value or std::nullopt).
Definition result.hpp:955
auto or_(R2 &&res) const
Returns res if the result is Err, otherwise returns self.
Definition result.hpp:985
const Result & inspect(F &&func) const noexcept(noexcept(func()))
Calls func() if Ok, returns self.
Definition result.hpp:909
static Result Ok() noexcept
Construct an Ok result.
Definition result.hpp:768
void unwrap() noexcept
Unwraps the value. Aborts if Err.
Definition result.hpp:805
auto map_or_else(D &&default_fn, F &&func) const
Applies a function if Ok, else computes a default with another function.
Definition result.hpp:1013
Result & operator=(const Result &other) noexcept(std::is_nothrow_copy_assignable_v< E >)
Definition result.hpp:1050
E & unwrap_err() noexcept
Unwraps the error. Aborts if Ok.
Definition result.hpp:817
Result< void, E2 > map_err(F &&func) const noexcept(noexcept(func(std::declval< E >())))
Maps the error if Err, else propagates Ok.
Definition result.hpp:850
void expect(const char msg[]) const noexcept
Unwraps the value or aborts with a custom message if Err.
Definition result.hpp:882
static Result Err(E err) noexcept
Construct an Err result.
Definition result.hpp:778
Result<T, E> - Holds either a value (Ok) or an error (Err).
Definition result.hpp:266
Result< T, E2 > map_err(F &&func) const noexcept(noexcept(func(std::declval< E >())))
Maps the error if Err, else propagates Ok.
Definition result.hpp:480
const E & expect_err(const char *msg) const noexcept
Definition result.hpp:419
T unwrap_or_default() const noexcept(std::is_nothrow_default_constructible_v< T >)
Returns the value if Ok, else returns a default-constructed value. Requires T to be default-construct...
Definition result.hpp:385
Result(const Result &other) noexcept(std::is_nothrow_copy_constructible_v< T > &&std::is_nothrow_copy_constructible_v< E >)
Definition result.hpp:697
auto map_or_else(D &&default_fn, F &&func) const
Applies a function to the value if Ok, else computes a default with another function.
Definition result.hpp:508
constexpr bool is_ok() const noexcept
Returns true if the result is Ok.
Definition result.hpp:304
T unwrap_or(T default_value) const noexcept
Returns value if Ok, else returns default_value.
Definition result.hpp:358
~Result()
Definition result.hpp:670
Result & operator=(Result &&other) noexcept(std::is_nothrow_move_assignable_v< T > &&std::is_nothrow_move_assignable_v< E >)
Definition result.hpp:683
bool contains(const T &value) const
Returns true if the result is Ok and contains the given value.
Definition result.hpp:613
T & expect(const char *msg) noexcept
Unwraps the value or aborts with a custom message if Err.
Definition result.hpp:399
bool is_err_and(Pred &&pred) const noexcept(noexcept(pred(std::declval< E >())))
Returns true if the result is Err and the predicate returns true for the error.
Definition result.hpp:449
auto and_(R2 &&res) const
Returns res if the result is Ok, otherwise returns self.
Definition result.hpp:539
auto or_else(F &&op) const
Calls op if the result is Err, otherwise returns self.
Definition result.hpp:566
auto flatten() const
Flattens a Result<Result<U, E>, E> into Result<U, E>.
Definition result.hpp:636
const Result & inspect(F &&func) const noexcept(noexcept(func(std::declval< const T & >())))
Calls func(value) if Ok, returns self.
Definition result.hpp:582
Result< U, E > map(F &&func) const noexcept(noexcept(func(std::declval< T >())))
Maps the value if Ok, else propagates Err.
Definition result.hpp:465
U map_or(U default_value, F &&func) const
Applies a function to the value if Ok, else returns default_value.
Definition result.hpp:494
const T & unwrap() const noexcept
Definition result.hpp:328
bool is_ok_and(Pred &&pred) const noexcept(noexcept(pred(std::declval< T >())))
Returns true if the result is Ok and the predicate returns true for the value.
Definition result.hpp:434
const T & expect(const char *msg) const noexcept
Definition result.hpp:403
R and_then(F &&func) const noexcept(noexcept(func(std::declval< T >())))
Chains another result-producing function if Ok, else propagates Err.
Definition result.hpp:525
std::optional< T > ok() const
Returns the value as std::optional if Ok, otherwise std::nullopt.
Definition result.hpp:653
auto or_(R2 &&res) const
Returns res if the result is Err, otherwise returns self.
Definition result.hpp:553
Result & operator=(const Result &other) noexcept(std::is_nothrow_copy_assignable_v< T > &&std::is_nothrow_copy_assignable_v< E >)
Definition result.hpp:707
E & unwrap_err() noexcept
Unwraps the error. Aborts if Ok.
Definition result.hpp:341
T & unwrap() noexcept
Unwraps the value. Aborts if Err.
Definition result.hpp:324
Result(Result &&other) noexcept(std::is_nothrow_move_constructible_v< T > &&std::is_nothrow_move_constructible_v< E >)
Definition result.hpp:673
T unwrap_or_else(F &&func) const noexcept(noexcept(func()))
Returns value if Ok, else calls func().
Definition result.hpp:371
const Result & inspect_err(F &&func) const noexcept(noexcept(func(std::declval< const E & >())))
Calls func(error) if Err, returns self.
Definition result.hpp:597
static Result Err(E err) noexcept
Construct an Err result.
Definition result.hpp:295
const E & unwrap_err() const noexcept
Definition result.hpp:345
static Result Ok(T val) noexcept
Construct an Ok result.
Definition result.hpp:282
bool contains_err(const E &error) const
Returns true if the result is Err and contains the given error.
Definition result.hpp:622
constexpr bool is_err() const noexcept
Returns true if the result is Err.
Definition result.hpp:313
E & expect_err(const char *msg) noexcept
Unwraps the error or aborts with a custom message if Ok.
Definition result.hpp:415
std::optional< E > err() const
Returns the error as std::optional if Err, otherwise std::nullopt.
Definition result.hpp:665
Definition result.hpp:251
Result< T, E > Err(E err)
Definition result.hpp:1073
Result< void, E > Ok()
Definition result.hpp:1076
#define EXPECT_OR_ABORT(cond, msg)
Definition result.hpp:242