cpp_result f19982d
Loading...
Searching...
No Matches
result.hpp
Go to the documentation of this file.
1// clang-format off
101// clang-format on
102// result.hpp - Rust-like Result<T, E> for C++17
103// SPDX-License-Identifier: MIT
104//
105// This header provides a modern, ergonomic Result type for C++17 inspired by
106// Rust. It supports combinators, helpers, and void specialization.
107//
108// All API is in the cpp_result namespace.
109//
110// --- API OVERVIEW ---
111//
112// Construction:
113// Result<T, E>::Ok(T)
114// Result<T, E>::Err(E)
115// Result<void, E>::Ok()
116// Result<void, E>::Err(E)
117// cpp_result::Ok<T, E>(T)
118// cpp_result::Err<T, E>(E)
119// cpp_result::Ok<E>()
120// cpp_result::Err<E>(E)
121//
122// Query:
123// is_ok(), is_err()
124//
125// Unwrap:
126// unwrap(), unwrap_err(), unwrap_or(value), unwrap_or_else(fn)
127// expect(msg), expect_err(msg)
128//
129// Combinators:
130// map(fn), map_err(fn), and_then(fn)
131// inspect(fn), inspect_err(fn)
132//
133// See the documentation below each function for usage examples.
134
135#pragma once
136
137#ifndef CPP_RESULT_HAS_STATEMENT_EXPR
138#if defined(__GNUC__) || defined(__clang__)
139#define CPP_RESULT_HAS_STATEMENT_EXPR 1
140#else
141#define CPP_RESULT_HAS_STATEMENT_EXPR 0
142#endif
143#endif
144
145#ifndef CPP_RESULT_FEATURE_ALL
146#define CPP_RESULT_FEATURE_ALL 1
147#endif
148#ifndef CPP_RESULT_FEATURE_UNWRAP
149#define CPP_RESULT_FEATURE_UNWRAP CPP_RESULT_FEATURE_ALL
150#endif
151#ifndef CPP_RESULT_FEATURE_MAP
152#define CPP_RESULT_FEATURE_MAP CPP_RESULT_FEATURE_ALL
153#endif
154#ifndef CPP_RESULT_FEATURE_ANDOR
155#define CPP_RESULT_FEATURE_ANDOR CPP_RESULT_FEATURE_ALL
156#endif
157#ifndef CPP_RESULT_FEATURE_INSPECT
158#define CPP_RESULT_FEATURE_INSPECT CPP_RESULT_FEATURE_ALL
159#endif
160#ifndef CPP_RESULT_FEATURE_CONTAINS
161#define CPP_RESULT_FEATURE_CONTAINS CPP_RESULT_FEATURE_ALL
162#endif
163#ifndef CPP_RESULT_FEATURE_FLATTEN
164#define CPP_RESULT_FEATURE_FLATTEN CPP_RESULT_FEATURE_ALL
165#endif
166#ifndef CPP_RESULT_FEATURE_OPTIONAL
167#define CPP_RESULT_FEATURE_OPTIONAL CPP_RESULT_FEATURE_ALL
168#endif
169
190#if CPP_RESULT_HAS_STATEMENT_EXPR
191#define TRY(expr) \
192 ({ \
193 auto &&__res = (expr); \
194 using __res_type = std::decay_t<decltype(__res)>; \
195 if (__res.is_err()) \
196 return __res_type::Err(__res.unwrap_err()); \
197 std::move(__res.unwrap()); \
198 })
199#else
200#define TRY(expr) \
201 ([&]() -> decltype(auto) { \
202 auto &&__res = (expr); \
203 using __res_type = std::decay_t<decltype(__res)>; \
204 if (__res.is_err()) \
205 return __res_type::Err(__res.unwrap_err()); \
206 return std::move(__res.unwrap()); \
207 }())
208#endif
209
210// clang-format off
228// clang-format on
229#define TRYL(name, expr) \
230 auto &&__res_##name = (expr); \
231 using __res_type_##name = std::decay_t<decltype(__res_##name)>; \
232 if (__res_##name.is_err()) \
233 return __res_type_##name::Err(__res_##name.unwrap_err()); \
234 auto &name = __res_##name.unwrap()
235
236#include <cstdio>
237#include <cstdlib>
238#if CPP_RESULT_FEATURE_OPTIONAL
239#include <optional>
240#endif // CPP_RESULT_FEATURE_OPTIONAL
241#include <type_traits>
242#include <utility>
243
244#define EXPECT_OR_ABORT(cond, msg) \
245 do { \
246 if (!(cond)) { \
247 std::fputs(msg, stderr); \
248 std::fputc('\n', stderr); \
249 std::abort(); \
250 } \
251 } while (0)
252
253namespace cpp_result {
254
268template <typename T, typename E> class [[nodiscard]] Result {
269 static_assert(!std::is_reference_v<T> && !std::is_reference_v<E>,
270 "Result<T,E> does not support reference types");
271
272public:
284 static inline Result Ok(T val) noexcept { return Result(std::move(val)); }
285
297 static inline Result Err(E err) noexcept { return Result(std::move(err)); }
298
306 constexpr bool is_ok() const noexcept { return is_ok_; }
307
315 constexpr bool is_err() const noexcept { return !is_ok_; }
316
317#if CPP_RESULT_FEATURE_UNWRAP
326 inline T &unwrap() noexcept {
327 EXPECT_OR_ABORT(is_ok_, "unwrap called on Result::Err()");
328 return data_.value;
329 }
330 inline const T &unwrap() const noexcept {
331 EXPECT_OR_ABORT(is_ok_, "unwrap called on Result::Err()");
332 return data_.value;
333 }
334
343 inline E &unwrap_err() noexcept {
344 EXPECT_OR_ABORT(!is_ok_, "unwrap_err called on Result::Ok()");
345 return data_.error;
346 }
347 inline const E &unwrap_err() const noexcept {
348 EXPECT_OR_ABORT(!is_ok_, "unwrap_err called on Result::Ok()");
349 return data_.error;
350 }
351
360 inline T unwrap_or(T default_value) const noexcept {
361 return is_ok_ ? data_.value : default_value;
362 }
363
372 template <typename F>
373 inline T unwrap_or_else(F &&func) const noexcept(noexcept(func())) {
374 return is_ok_ ? data_.value : std::forward<F>(func)();
375 }
376
388 noexcept(std::is_nothrow_default_constructible_v<T>) {
389 if (is_ok_)
390 return data_.value;
391 return T{};
392 }
393
401 T &expect(const char *msg) noexcept {
402 EXPECT_OR_ABORT(is_ok_, msg);
403 return data_.value;
404 }
405 const T &expect(const char *msg) const noexcept {
406 EXPECT_OR_ABORT(is_ok_, msg);
407 return data_.value;
408 }
409
417 E &expect_err(const char *msg) noexcept {
418 EXPECT_OR_ABORT(!is_ok_, msg);
419 return data_.error;
420 }
421 const E &expect_err(const char *msg) const noexcept {
422 EXPECT_OR_ABORT(!is_ok_, msg);
423 return data_.error;
424 }
425
435 template <typename Pred>
436 bool is_ok_and(Pred &&pred) const
437 noexcept(noexcept(pred(std::declval<T>()))) {
438 return is_ok_ && pred(data_.value);
439 }
440
450 template <typename Pred>
451 bool is_err_and(Pred &&pred) const
452 noexcept(noexcept(pred(std::declval<E>()))) {
453 return !is_ok_ && pred(data_.error);
454 }
455#endif // CPP_RESULT_FEATURE_UNWRAP
456
457#if CPP_RESULT_FEATURE_MAP
466 template <typename F, typename U = std::invoke_result_t<F, T>>
467 Result<U, E> map(F &&func) const noexcept(noexcept(func(std::declval<T>()))) {
468 if (is_ok_)
469 return Result<U, E>::Ok(func(data_.value));
470 return Result<U, E>::Err(data_.error);
471 }
472
481 template <typename F, typename E2 = std::invoke_result_t<F, E>>
482 Result<T, E2> map_err(F &&func) const
483 noexcept(noexcept(func(std::declval<E>()))) {
484 if (is_ok_)
485 return Result<T, E2>::Ok(data_.value);
486 return Result<T, E2>::Err(func(data_.error));
487 }
488
496 template <typename U, typename F> U map_or(U default_value, F &&func) const {
497 return is_ok_ ? func(data_.value) : default_value;
498 }
499
509 template <typename D, typename F>
510 auto map_or_else(D &&default_fn, F &&func) const {
511 return is_ok_ ? func(data_.value) : default_fn();
512 }
513#endif // CPP_RESULT_FEATURE_MAP
514
515#if CPP_RESULT_FEATURE_ANDOR
526 template <typename F, typename R = typename std::invoke_result_t<F, T>>
527 R and_then(F &&func) const noexcept(noexcept(func(std::declval<T>()))) {
528 if (is_ok_)
529 return func(data_.value);
530 return R::Err(data_.error);
531 }
532
541 template <typename R2> auto and_(R2 &&res) const {
542 if (is_ok_)
543 return std::forward<R2>(res);
544 return Result<T, E>::Err(data_.error);
545 }
546
555 template <typename R2> auto or_(R2 &&res) const {
556 if (!is_ok_)
557 return std::forward<R2>(res);
558 return *this;
559 }
560
568 template <typename F> auto or_else(F &&op) const {
569 if (!is_ok_)
570 return op();
571 return *this;
572 }
573#endif // CPP_RESULT_FEATURE_ANDOR
574
575#if CPP_RESULT_FEATURE_INSPECT
583 template <typename F>
584 const Result &inspect(F &&func) const
585 noexcept(noexcept(func(std::declval<const T &>()))) {
586 if (is_ok_)
587 func(data_.value);
588 return *this;
589 }
590
598 template <typename F>
599 const Result &inspect_err(F &&func) const
600 noexcept(noexcept(func(std::declval<const E &>()))) {
601 if (!is_ok_)
602 func(data_.error);
603 return *this;
604 }
605#endif // CPP_RESULT_FEATURE_INSPECT
606
607#if CPP_RESULT_FEATURE_CONTAINS
615 bool contains(const T &value) const { return is_ok_ && data_.value == value; }
616
624 bool contains_err(const E &error) const {
625 return !is_ok_ && data_.error == error;
626 }
627#endif // CPP_RESULT_FEATURE_CONTAINS
628
629#if CPP_RESULT_FEATURE_FLATTEN
638 auto flatten() const {
639 using Inner = decltype(data_.value);
640 if (is_ok_)
641 return data_.value;
642 return Inner::Err(data_.error);
643 }
644#endif // CPP_RESULT_FEATURE_FLATTEN
645
646#if CPP_RESULT_FEATURE_OPTIONAL
655 std::optional<T> ok() const {
656 return is_ok_ ? std::optional<T>(data_.value) : std::nullopt;
657 }
658
667 std::optional<E> err() const {
668 return !is_ok_ ? std::optional<E>(data_.error) : std::nullopt;
669 }
670#endif
671
672 ~Result() { destroy(); }
673
674 // Move semantics
675 Result(Result &&other) noexcept(std::is_nothrow_move_constructible_v<T> &&
676 std::is_nothrow_move_constructible_v<E>)
677 : is_ok_(other.is_ok_) {
678 if (is_ok_)
679 new (&data_.value) T(std::move(other.data_.value));
680 else
681 new (&data_.error) E(std::move(other.data_.error));
682 }
683
684 Result &
685 operator=(Result &&other) noexcept(std::is_nothrow_move_assignable_v<T> &&
686 std::is_nothrow_move_assignable_v<E>) {
687 if (this != &other) {
688 destroy();
689 is_ok_ = other.is_ok_;
690 if (is_ok_)
691 new (&data_.value) T(std::move(other.data_.value));
692 else
693 new (&data_.error) E(std::move(other.data_.error));
694 }
695 return *this;
696 }
697
698 // Conditional copy semantics
699 Result(const Result &other) noexcept(
700 std::is_nothrow_copy_constructible_v<T> &&
701 std::is_nothrow_copy_constructible_v<E>)
702 : is_ok_(other.is_ok_) {
703 if (is_ok_)
704 new (&data_.value) T(other.data_.value);
705 else
706 new (&data_.error) E(other.data_.error);
707 }
708
709 Result &operator=(const Result &other) noexcept(
710 std::is_nothrow_copy_assignable_v<T> &&
711 std::is_nothrow_copy_assignable_v<E>) {
712 if (this != &other) {
713 destroy();
714 is_ok_ = other.is_ok_;
715 if (is_ok_)
716 new (&data_.value) T(other.data_.value);
717 else
718 new (&data_.error) E(other.data_.error);
719 }
720 return *this;
721 }
722
723private:
724 union Data {
725 T value;
726 E error;
727 Data() {}
728 ~Data() {}
729 } data_;
730 bool is_ok_;
731
732 explicit Result(T val) noexcept : is_ok_(true) {
733 new (&data_.value) T(std::move(val));
734 }
735
736 explicit Result(E err) noexcept : is_ok_(false) {
737 new (&data_.error) E(std::move(err));
738 }
739
740 void destroy() noexcept { is_ok_ ? data_.value.~T() : data_.error.~E(); }
741};
742
758template <typename E> class [[nodiscard]] Result<void, E> {
759 static_assert(!std::is_reference_v<E>,
760 "Result<void,E> does not support reference types");
761
762public:
770 static inline Result Ok() noexcept { return Result(); }
771
780 static inline Result Err(E err) noexcept { return Result(std::move(err)); }
781
789 inline bool is_ok() const noexcept { return is_ok_; }
790
798 inline bool is_err() const noexcept { return !is_ok_; }
799
807 inline void unwrap() noexcept {
808 EXPECT_OR_ABORT(is_ok_, "unwrap called on Result::Err()");
809 }
810
819 inline E &unwrap_err() noexcept {
820 EXPECT_OR_ABORT(!is_ok_, "unwrap_err called on Result::Ok()");
821 return error_;
822 }
823 inline const E &unwrap_err() const noexcept {
824 EXPECT_OR_ABORT(!is_ok_, "unwrap_err called on Result::Ok()");
825 return error_;
826 }
827
836 template <typename F, typename U = std::invoke_result_t<F>>
837 Result<U, E> map(F &&func) const noexcept(noexcept(func())) {
838 if (is_ok_)
839 return Result<U, E>::Ok(func());
840 return Result<U, E>::Err(error_);
841 }
842
851 template <typename F, typename E2 = std::invoke_result_t<F, E>>
852 Result<void, E2> map_err(F &&func) const
853 noexcept(noexcept(func(std::declval<E>()))) {
854 if (is_ok_)
855 return Result<void, E2>::Ok();
856 return Result<void, E2>::Err(func(error_));
857 }
858
870 template <typename F, typename R = std::invoke_result_t<F>>
871 R and_then(F &&func) const noexcept(noexcept(func())) {
872 if (is_ok_)
873 return func();
874 return R::Err(error_);
875 }
876
884 void expect(const char msg[]) const noexcept { EXPECT_OR_ABORT(is_ok_, msg); }
885
893 E &expect_err(const char msg[]) noexcept {
894 EXPECT_OR_ABORT(!is_ok_, msg);
895 return error_;
896 }
897
898 const E &expect_err(const char msg[]) const noexcept {
899 EXPECT_OR_ABORT(!is_ok_, msg);
900 return error_;
901 }
902
910 template <typename F>
911 const Result &inspect(F &&func) const noexcept(noexcept(func())) {
912 if (is_ok_)
913 func();
914 return *this;
915 }
916
924 template <typename F>
925 const Result &inspect_err(F &&func) const
926 noexcept(noexcept(func(std::declval<const E &>()))) {
927 if (!is_ok_)
928 func(error_);
929 return *this;
930 }
931
941 template <typename Pred>
942 bool is_err_and(Pred &&pred) const
943 noexcept(noexcept(pred(std::declval<E>()))) {
944 return !is_ok_ && pred(error_);
945 }
946
957 std::optional<E> err() const {
958 if (!is_ok_)
959 return error_;
960 return std::nullopt;
961 }
962
972 template <typename R2> auto and_(R2 &&res) const {
973 if (is_ok_)
974 return std::forward<R2>(res);
975 return Result<void, E>::Err(error_);
976 }
977
987 template <typename R2> auto or_(R2 &&res) const {
988 if (!is_ok_)
989 return std::forward<R2>(res);
990 return *this;
991 }
992
1001 template <typename U, typename F> U map_or(U default_value, F &&func) const {
1002 return is_ok_ ? func() : default_value;
1003 }
1004
1014 template <typename D, typename F>
1015 auto map_or_else(D &&default_fn, F &&func) const {
1016 return is_ok_ ? func() : default_fn();
1017 }
1018
1026 bool contains_err(const E &error) const { return !is_ok_ && error_ == error; }
1027
1028 // Move semantics
1029 Result(Result &&other) noexcept(std::is_nothrow_move_constructible_v<E>)
1030 : is_ok_(other.is_ok_) {
1031 if (!is_ok_)
1032 new (&error_) E(std::move(other.error_));
1033 }
1034
1035 Result &
1036 operator=(Result &&other) noexcept(std::is_nothrow_move_assignable_v<E>) {
1037 if (this != &other) {
1038 is_ok_ = other.is_ok_;
1039 if (!is_ok_)
1040 new (&error_) E(std::move(other.error_));
1041 }
1042 return *this;
1043 }
1044
1045 // Conditional copy semantics
1046 Result(const Result &other) noexcept(std::is_nothrow_copy_constructible_v<E>)
1047 : is_ok_(other.is_ok_) {
1048 if (!is_ok_)
1049 new (&error_) E(other.error_);
1050 }
1051
1052 Result &operator=(const Result &other) noexcept(
1053 std::is_nothrow_copy_assignable_v<E>) {
1054 if (this != &other) {
1055 is_ok_ = other.is_ok_;
1056 if (!is_ok_)
1057 new (&error_) E(other.error_);
1058 }
1059 return *this;
1060 }
1061
1062private:
1063 E error_;
1064 bool is_ok_;
1065
1066 Result() noexcept : is_ok_(true) {}
1067 explicit Result(E err) noexcept : is_ok_(false) {
1068 new (&error_) E(std::move(err));
1069 }
1070};
1071
1072template <typename T, typename E> inline Result<T, E> Ok(T val) {
1073 return Result<T, E>::Ok(std::move(val));
1074}
1075template <typename T, typename E> inline Result<T, E> Err(E err) {
1076 return Result<T, E>::Err(std::move(err));
1077}
1078template <typename E> inline Result<void, E> Ok() {
1079 return Result<void, E>::Ok();
1080}
1081template <typename E> inline Result<void, E> Err(E err) {
1082 return Result<void, E>::Err(std::move(err));
1083}
1084
1085} // namespace cpp_result
Result(const Result &other) noexcept(std::is_nothrow_copy_constructible_v< E >)
Definition result.hpp:1046
bool contains_err(const E &error) const
Returns true if the result is Err and contains the given error.
Definition result.hpp:1026
bool is_err() const noexcept
Returns true if the result is Err.
Definition result.hpp:798
const E & unwrap_err() const noexcept
Definition result.hpp:823
Result & operator=(Result &&other) noexcept(std::is_nothrow_move_assignable_v< E >)
Definition result.hpp:1036
Result< U, E > map(F &&func) const noexcept(noexcept(func()))
Returns unit type if Ok, else returns error.
Definition result.hpp:837
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:942
bool is_ok() const noexcept
Returns true if the result is Ok.
Definition result.hpp:789
auto and_(R2 &&res) const
Returns res if the result is Ok, otherwise returns self.
Definition result.hpp:972
E & expect_err(const char msg[]) noexcept
Unwraps the error or aborts with a custom message if Ok.
Definition result.hpp:893
Result(Result &&other) noexcept(std::is_nothrow_move_constructible_v< E >)
Definition result.hpp:1029
const E & expect_err(const char msg[]) const noexcept
Definition result.hpp:898
const Result & inspect_err(F &&func) const noexcept(noexcept(func(std::declval< const E & >())))
Calls func(error) if Err, returns self.
Definition result.hpp:925
R and_then(F &&func) const noexcept(noexcept(func()))
Chains another result-producing function if Ok, else propagates Err.
Definition result.hpp:871
U map_or(U default_value, F &&func) const
Applies a function if Ok, else returns default_value.
Definition result.hpp:1001
std::optional< E > err() const
Converts the Result into a std::optional<E> (Err value or std::nullopt).
Definition result.hpp:957
auto or_(R2 &&res) const
Returns res if the result is Err, otherwise returns self.
Definition result.hpp:987
const Result & inspect(F &&func) const noexcept(noexcept(func()))
Calls func() if Ok, returns self.
Definition result.hpp:911
static Result Ok() noexcept
Construct an Ok result.
Definition result.hpp:770
void unwrap() noexcept
Unwraps the value. Aborts if Err.
Definition result.hpp:807
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:1015
Result & operator=(const Result &other) noexcept(std::is_nothrow_copy_assignable_v< E >)
Definition result.hpp:1052
E & unwrap_err() noexcept
Unwraps the error. Aborts if Ok.
Definition result.hpp:819
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:852
void expect(const char msg[]) const noexcept
Unwraps the value or aborts with a custom message if Err.
Definition result.hpp:884
static Result Err(E err) noexcept
Construct an Err result.
Definition result.hpp:780
Result<T, E> - Holds either a value (Ok) or an error (Err).
Definition result.hpp:268
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:482
const E & expect_err(const char *msg) const noexcept
Definition result.hpp:421
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:387
Result(const Result &other) noexcept(std::is_nothrow_copy_constructible_v< T > &&std::is_nothrow_copy_constructible_v< E >)
Definition result.hpp:699
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:510
constexpr bool is_ok() const noexcept
Returns true if the result is Ok.
Definition result.hpp:306
T unwrap_or(T default_value) const noexcept
Returns value if Ok, else returns default_value.
Definition result.hpp:360
~Result()
Definition result.hpp:672
Result & operator=(Result &&other) noexcept(std::is_nothrow_move_assignable_v< T > &&std::is_nothrow_move_assignable_v< E >)
Definition result.hpp:685
bool contains(const T &value) const
Returns true if the result is Ok and contains the given value.
Definition result.hpp:615
T & expect(const char *msg) noexcept
Unwraps the value or aborts with a custom message if Err.
Definition result.hpp:401
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:451
auto and_(R2 &&res) const
Returns res if the result is Ok, otherwise returns self.
Definition result.hpp:541
auto or_else(F &&op) const
Calls op if the result is Err, otherwise returns self.
Definition result.hpp:568
auto flatten() const
Flattens a Result<Result<U, E>, E> into Result<U, E>.
Definition result.hpp:638
const Result & inspect(F &&func) const noexcept(noexcept(func(std::declval< const T & >())))
Calls func(value) if Ok, returns self.
Definition result.hpp:584
Result< U, E > map(F &&func) const noexcept(noexcept(func(std::declval< T >())))
Maps the value if Ok, else propagates Err.
Definition result.hpp:467
U map_or(U default_value, F &&func) const
Applies a function to the value if Ok, else returns default_value.
Definition result.hpp:496
const T & unwrap() const noexcept
Definition result.hpp:330
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:436
const T & expect(const char *msg) const noexcept
Definition result.hpp:405
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:527
std::optional< T > ok() const
Returns the value as std::optional if Ok, otherwise std::nullopt.
Definition result.hpp:655
auto or_(R2 &&res) const
Returns res if the result is Err, otherwise returns self.
Definition result.hpp:555
Result & operator=(const Result &other) noexcept(std::is_nothrow_copy_assignable_v< T > &&std::is_nothrow_copy_assignable_v< E >)
Definition result.hpp:709
E & unwrap_err() noexcept
Unwraps the error. Aborts if Ok.
Definition result.hpp:343
T & unwrap() noexcept
Unwraps the value. Aborts if Err.
Definition result.hpp:326
Result(Result &&other) noexcept(std::is_nothrow_move_constructible_v< T > &&std::is_nothrow_move_constructible_v< E >)
Definition result.hpp:675
T unwrap_or_else(F &&func) const noexcept(noexcept(func()))
Returns value if Ok, else calls func().
Definition result.hpp:373
const Result & inspect_err(F &&func) const noexcept(noexcept(func(std::declval< const E & >())))
Calls func(error) if Err, returns self.
Definition result.hpp:599
static Result Err(E err) noexcept
Construct an Err result.
Definition result.hpp:297
const E & unwrap_err() const noexcept
Definition result.hpp:347
static Result Ok(T val) noexcept
Construct an Ok result.
Definition result.hpp:284
bool contains_err(const E &error) const
Returns true if the result is Err and contains the given error.
Definition result.hpp:624
constexpr bool is_err() const noexcept
Returns true if the result is Err.
Definition result.hpp:315
E & expect_err(const char *msg) noexcept
Unwraps the error or aborts with a custom message if Ok.
Definition result.hpp:417
std::optional< E > err() const
Returns the error as std::optional if Err, otherwise std::nullopt.
Definition result.hpp:667
Definition result.hpp:253
Result< T, E > Err(E err)
Definition result.hpp:1075
Result< void, E > Ok()
Definition result.hpp:1078
#define EXPECT_OR_ABORT(cond, msg)
Definition result.hpp:244