diff --git a/classres_1_1result-members.html b/classres_1_1result-members.html index 8829ead..39734ae 100644 --- a/classres_1_1result-members.html +++ b/classres_1_1result-members.html @@ -141,12 +141,13 @@ err (defined in res::result< T, E >)res::result< T, E >friend error() const -> const E & (defined in res::result< T, E >)res::result< T, E >inline is_ok() const -> bool (defined in res::result< T, E >)res::result< T, E >inline - map(F &&functor) const -> result< U, E > (defined in res::result< T, E >)res::result< T, E >inline - ok (defined in res::result< T, E >)res::result< T, E >friend - operator bool() const (defined in res::result< T, E >)res::result< T, E >inlineexplicit - operator!() const -> bool (defined in res::result< T, E >)res::result< T, E >inline - value() const -> const T & (defined in res::result< T, E >)res::result< T, E >inline - value_or(T &&default_value) const -> T (defined in res::result< T, E >)res::result< T, E >inline + map(F &&functor) const -> result< R, E > (defined in res::result< T, E >)res::result< T, E >inline + map_err(F &&functor) const -> result< T, U > (defined in res::result< T, E >)res::result< T, E >inline + ok (defined in res::result< T, E >)res::result< T, E >friend + operator bool() const (defined in res::result< T, E >)res::result< T, E >inlineexplicit + operator!() const -> bool (defined in res::result< T, E >)res::result< T, E >inline + value() const -> const T & (defined in res::result< T, E >)res::result< T, E >inline + value_or(T &&default_value) const -> T (defined in res::result< T, E >)res::result< T, E >inline diff --git a/classres_1_1result.html b/classres_1_1result.html index a6bb3c5..34b4a30 100644 --- a/classres_1_1result.html +++ b/classres_1_1result.html @@ -165,10 +165,14 @@ auto error () const -> const E &   - -template<typename F , typename U = std::invoke_result_t<F, T>> -auto map (F &&functor) const -> result< U, E > -  + +template<typename F , typename R = std::invoke_result_t<F, T>> +auto map (F &&functor) const -> result< R, E > +  + +template<typename F , typename U = std::invoke_result_t<F, E>> +auto map_err (F &&functor) const -> result< T, U > +  diff --git a/classres_1_1result_3_01void_00_01E_01_4-members.html b/classres_1_1result_3_01void_00_01E_01_4-members.html index f882de3..2ff987c 100644 --- a/classres_1_1result_3_01void_00_01E_01_4-members.html +++ b/classres_1_1result_3_01void_00_01E_01_4-members.html @@ -141,10 +141,11 @@ - - - - + + + + +

Friends

err (defined in res::result< void, E >)res::result< void, E >friend
error() const -> const E & (defined in res::result< void, E >)res::result< void, E >inline
is_ok() const -> bool (defined in res::result< void, E >)res::result< void, E >inline
map(F &&functor) const -> result< U, E > (defined in res::result< void, E >)res::result< void, E >inline
ok (defined in res::result< void, E >)res::result< void, E >friend
operator bool() const (defined in res::result< void, E >)res::result< void, E >inlineexplicit
operator!() const -> bool (defined in res::result< void, E >)res::result< void, E >inline
map(F &&functor) const -> result< R, E > (defined in res::result< void, E >)res::result< void, E >inline
map_err(F &&functor) const -> result< void, U > (defined in res::result< void, E >)res::result< void, E >inline
ok (defined in res::result< void, E >)res::result< void, E >friend
operator bool() const (defined in res::result< void, E >)res::result< void, E >inlineexplicit
operator!() const -> bool (defined in res::result< void, E >)res::result< void, E >inline
diff --git a/classres_1_1result_3_01void_00_01E_01_4.html b/classres_1_1result_3_01void_00_01E_01_4.html index 1c903fb..1f3c450 100644 --- a/classres_1_1result_3_01void_00_01E_01_4.html +++ b/classres_1_1result_3_01void_00_01E_01_4.html @@ -159,10 +159,14 @@ auto error () const -> const E &   - -template<typename F , typename U = std::invoke_result_t<F>> -auto map (F &&functor) const -> result< U, E > -  + +template<typename F , typename R = std::invoke_result_t<F>> +auto map (F &&functor) const -> result< R, E > +  + +template<typename F , typename U = std::invoke_result_t<F, E>> +auto map_err (F &&functor) const -> result< void, U > +  diff --git a/result_8h.html b/result_8h.html index 59b854f..2d89bec 100644 --- a/result_8h.html +++ b/result_8h.html @@ -140,7 +140,8 @@

result is a C++ library that provides a Result<T, E> type, which can be used to return and propagate errors. It's inspired by Rust's std::Result type. More...

-
#include <stdexcept>
+
#include <optional>
+#include <stdexcept>
#include <utility>
#include <variant>
diff --git a/result_8h_source.html b/result_8h_source.html index cec3776..cac73b6 100644 --- a/result_8h_source.html +++ b/result_8h_source.html @@ -140,170 +140,172 @@
14#ifndef RESULT_LIB
15#define RESULT_LIB
16
-
17#include <stdexcept>
-
18#include <utility>
-
19
-
20namespace res {
+
17#include <optional>
+
18#include <stdexcept>
+
19#include <utility>
+
20#include <variant>
21
-
22template <typename T, typename E> class result;
-
23template <typename E> class result<void, E>;
-
24
-
28template <typename E> class err {
-
29 E error_;
-
30
-
31public:
-
32 err() = delete;
-
33 explicit err(E error) : error_(std::move(error)) {}
-
34
-
35 template <typename T> operator result<T, E>() const; // NOLINT(google-explicit-constructor)
-
36 operator result<void, E>() const; // NOLINT(google-explicit-constructor)
-
37};
-
38
-
39template <typename E> template <typename T> inline err<E>::operator result<T, E>() const {
-
40 return result<T, E>(result<T, E>::Unsuccessful::UNSUCCESSFUL, error_);
-
41}
-
42
-
43template <typename E> inline err<E>::operator result<void, E>() const {
-
44 return result<void, E>(result<void, E>::Unsuccessful::UNSUCCESSFUL, error_);
-
45}
-
46
-
47} // namespace res
+
22namespace res {
+
23
+
24template <typename T, typename E> class result;
+
25template <typename E> class result<void, E>;
+
26
+
30template <typename E> class err {
+
31 E error_;
+
32
+
33public:
+
34 err() = delete;
+
35 explicit err(E error) : error_(std::move(error)) {}
+
36
+
37 template <typename T> operator result<T, E>() const; // NOLINT(google-explicit-constructor)
+
38 operator result<void, E>() const; // NOLINT(google-explicit-constructor)
+
39};
+
40
+
41template <typename E> template <typename T> inline err<E>::operator result<T, E>() const {
+
42 return result<T, E>(result<T, E>::Unsuccessful::UNSUCCESSFUL, error_);
+
43}
+
44
+
45template <typename E> inline err<E>::operator result<void, E>() const {
+
46 return result<void, E>(result<void, E>::Unsuccessful::UNSUCCESSFUL, error_);
+
47}
48
-
49#include <variant>
+
49} // namespace res
50
-
51namespace res {
+
51#include <variant>
52
-
53template <typename T, typename E> class result;
-
54template <typename E> class result<void, E>;
-
55
-
59template <typename T = std::monostate> class ok {
-
60 T value_;
-
61
-
62public:
-
63 ok() = default;
-
64 explicit ok(T value) : value_(std::move(value)) {}
-
65
-
66 template <typename E> operator result<T, E>() const; // NOLINT(google-explicit-constructor)
-
67 template <typename E> operator result<void, E>() const; // NOLINT(google-explicit-constructor)
-
68};
-
69
-
70template <typename T> template <typename E> inline ok<T>::operator result<T, E>() const {
-
71 return result<T, E>(result<T, E>::Successful::SUCCESSFUL, value_);
-
72}
-
73
-
74template <typename T> template <typename E> inline ok<T>::operator result<void, E>() const {
-
75 return result<void, E>(result<void, E>::Successful::SUCCESSFUL);
-
76}
-
77
-
78} // namespace res
+
53namespace res {
+
54
+
55template <typename T, typename E> class result;
+
56template <typename E> class result<void, E>;
+
57
+
61template <typename T = std::monostate> class ok {
+
62 T value_;
+
63
+
64public:
+
65 ok() = default;
+
66 explicit ok(T value) : value_(std::move(value)) {}
+
67
+
68 template <typename E> operator result<T, E>() const; // NOLINT(google-explicit-constructor)
+
69 template <typename E> operator result<void, E>() const; // NOLINT(google-explicit-constructor)
+
70};
+
71
+
72template <typename T> template <typename E> inline ok<T>::operator result<T, E>() const {
+
73 return result<T, E>(result<T, E>::Successful::SUCCESSFUL, value_);
+
74}
+
75
+
76template <typename T> template <typename E> inline ok<T>::operator result<void, E>() const {
+
77 return result<void, E>(result<void, E>::Successful::SUCCESSFUL);
+
78}
79
-
80namespace res {
+
80} // namespace res
81
-
88template <typename T, typename E> class result {
-
89 static_assert(!std::is_same_v<T, void>, "T (value type) must not be void");
-
90 static_assert(!std::is_same_v<E, void>, "E (error type) must not be void");
-
91
-
92 bool successful_;
-
93 T value_;
-
94 E error_;
+
82namespace res {
+
83
+
90template <typename T, typename E> class result {
+
91 static_assert(!std::is_same_v<T, void>, "T (value type) must not be void");
+
92 static_assert(!std::is_same_v<E, void>, "E (error type) must not be void");
+
93
+
94 std::variant<T, E> content_;
95
-
96 // Named constructors
+
96 // Simulate named constructors
97 enum Successful { SUCCESSFUL };
98 enum Unsuccessful { UNSUCCESSFUL };
-
99 result(Successful successful, T value) : successful_(true), value_(std::move(value)) {}
-
100 result(Unsuccessful unsuccessful, E error) : successful_(false), error_(std::move(error)) {}
+
99 result(Successful successful, T value) { content_.template emplace<0>(std::move(value)); }
+
100 result(Unsuccessful unsuccessful, E error) { content_.template emplace<1>(std::move(error)); }
101
-
102 auto make_successful(T value) -> void {
-
103 successful_ = true;
-
104 value_ = std::move(value);
-
105 }
-
106 auto make_unsuccessful(E error) -> void {
-
107 successful_ = false;
-
108 error_ = std::move(error);
-
109 }
+
102 template <typename U> friend class ok;
+
103 template <typename U> friend class err;
+
104
+
105public:
+
106 // Observers
+
107 [[nodiscard]] auto is_ok() const -> bool { return content_.index() == 0; }
+
108 explicit operator bool() const { return is_ok(); }
+
109 auto operator!() const -> bool { return !is_ok(); }
110
-
111 template <typename U> friend class ok;
-
112 template <typename U> friend class err;
-
113
-
114public:
-
115 // Observers
-
116 [[nodiscard]] auto is_ok() const -> bool { return successful_; }
-
117 explicit operator bool() const { return is_ok(); }
-
118 auto operator!() const -> bool { return !is_ok(); }
-
119
-
120 [[nodiscard]] auto value() const -> const T &;
-
121 [[nodiscard]] auto value_or(T &&default_value) const -> T;
-
122 [[nodiscard]] auto error() const -> const E &;
-
123
-
124 // Monadic operations
-
125 // map method gets functor F(T x) -> U as an argument and returns result of applying this functor to the value of the
-
126 // result object. If the result object is an error, the functor is not called and the error is propagated. But the
-
127 // result value type is changed to U.
-
128 template <typename F, typename U = std::invoke_result_t<F, T>> auto map(F &&functor) const -> result<U, E> {
-
129 if (is_ok()) { return ok<U>(std::forward<F>(functor)(value_)); }
-
130 return err<E>(error_);
-
131 }
-
132};
-
133
-
135template <typename E> class result<void, E> {
-
136 static_assert(!std::is_same_v<E, void>, "E (error type) must not be void");
+
111 [[nodiscard]] auto value() const -> const T &;
+
112 [[nodiscard]] auto value_or(T &&default_value) const -> T;
+
113 [[nodiscard]] auto error() const -> const E &;
+
114
+
115 // Monadic operations
+
116 // map method gets functor F(T x) -> R as an argument and returns result of applying this functor to the value of the
+
117 // result object. If the result object is an error, the functor is not called and the error is propagated. But the
+
118 // result value type is changed to R.
+
119 template <typename F, typename R = std::invoke_result_t<F, T>> auto map(F &&functor) const -> result<R, E> {
+
120 if (is_ok()) { return ok<R>(std::forward<F>(functor)(value())); }
+
121 return err<E>(error());
+
122 }
+
123 // map_err method gets functor F(E x) -> U as an argument and returns result of applying this functor to the error of
+
124 // the result object. If the result object is a success, the functor is not called and the value is propagated. But
+
125 // the result error type is changed to U.
+
126 template <typename F, typename U = std::invoke_result_t<F, E>> auto map_err(F &&functor) const -> result<T, U> {
+
127 if (!is_ok()) { return err<U>(std::forward<F>(functor)(error())); }
+
128 return ok<T>(value());
+
129 }
+
130};
+
131
+
133template <typename E> class result<void, E> {
+
134 static_assert(!std::is_same_v<E, void>, "E (error type) must not be void");
+
135
+
136 std::optional<E> error_;
137
-
138 bool successful_;
-
139 E error_;
-
140
-
141 // Named constructors
-
142 enum Successful { SUCCESSFUL };
-
143 enum Unsuccessful { UNSUCCESSFUL };
-
144 explicit result(Successful successful) : successful_(true) {}
-
145 result(Unsuccessful unsuccessful, E error) : successful_(false), error_(std::move(error)) {}
+
138 // Simulate named constructors
+
139 enum Successful { SUCCESSFUL };
+
140 enum Unsuccessful { UNSUCCESSFUL };
+
141 explicit result(Successful successful) {}
+
142 result(Unsuccessful unsuccessful, E error) : error_(std::move(error)) {}
+
143
+
144 template <typename U> friend class ok;
+
145 template <typename U> friend class err;
146
-
147 template <typename U> friend class ok;
-
148 template <typename U> friend class err;
-
149
-
150public:
-
151 // Observers
-
152 [[nodiscard]] auto is_ok() const -> bool { return successful_; }
-
153 explicit operator bool() const { return is_ok(); }
-
154 auto operator!() const -> bool { return !is_ok(); }
-
155
-
156 [[nodiscard]] auto error() const -> const E &;
-
157
-
158 // Monadic operations
-
159 // map method gets functor F() -> U as an argument and returns result of applying this functor to the value of the
-
160 // result object. If the result object is an error, the functor is not called and the error is propagated. But the
-
161 // result value type is changed to U.
-
162 template <typename F, typename U = std::invoke_result_t<F>> auto map(F &&functor) const -> result<U, E> {
-
163 if (is_ok()) { return ok<U>(std::forward<F>(functor)()); }
-
164 return err<E>(error_);
-
165 }
-
166};
-
167
-
168template <typename T, typename E> inline auto result<T, E>::value() const -> const T & {
-
169 if (!is_ok()) { throw std::logic_error("value() called on result with error"); }
-
170 return value_;
-
171}
-
172
-
173template <typename T, typename E> inline auto result<T, E>::value_or(T &&default_value) const -> T {
-
174 if (is_ok()) { return value_; }
-
175 return std::move(default_value);
-
176}
-
177
-
178template <typename T, typename E> inline auto result<T, E>::error() const -> const E & {
-
179 if (is_ok()) { throw std::logic_error("error() called on result with value"); }
-
180 return error_;
-
181}
-
182
-
183template <typename E> inline auto result<void, E>::error() const -> const E & {
-
184 if (is_ok()) { throw std::logic_error("error() called on result with value"); }
-
185 return error_;
-
186}
-
187
-
188} // namespace res
+
147public:
+
148 // Observers
+
149 [[nodiscard]] auto is_ok() const -> bool { return !error_.has_value(); }
+
150 explicit operator bool() const { return is_ok(); }
+
151 auto operator!() const -> bool { return !is_ok(); }
+
152
+
153 [[nodiscard]] auto error() const -> const E &;
+
154
+
155 // Monadic operations
+
156 // map method gets functor F() -> R as an argument and returns result of applying this functor to the value of the
+
157 // result object. If the result object is an error, the functor is not called and the error is propagated. But the
+
158 // result value type is changed to R.
+
159 template <typename F, typename R = std::invoke_result_t<F>> auto map(F &&functor) const -> result<R, E> {
+
160 if (is_ok()) { return ok<R>(std::forward<F>(functor)()); }
+
161 return err<E>(error_.value());
+
162 }
+
163 // map_err method for void value type is same as for non-void value type because it does not depend on the value type.
+
164 template <typename F, typename U = std::invoke_result_t<F, E>> auto map_err(F &&functor) const -> result<void, U> {
+
165 if (!is_ok()) { return err<U>(std::forward<F>(functor)(error_.value())); }
+
166 return ok();
+
167 }
+
168};
+
169
+
170template <typename T, typename E> inline auto result<T, E>::value() const -> const T & {
+
171 if (!is_ok()) { throw std::logic_error("value() called on result with error"); }
+
172 return std::get<0>(content_);
+
173}
+
174
+
175template <typename T, typename E> inline auto result<T, E>::value_or(T &&default_value) const -> T {
+
176 if (is_ok()) { return std::get<0>(content_); }
+
177 return std::move(default_value);
+
178}
+
179
+
180template <typename T, typename E> inline auto result<T, E>::error() const -> const E & {
+
181 if (is_ok()) { throw std::logic_error("error() called on result with value"); }
+
182 return std::get<1>(content_);
+
183}
+
184
+
185template <typename E> inline auto result<void, E>::error() const -> const E & {
+
186 if (is_ok()) { throw std::logic_error("error() called on result with value"); }
+
187 return error_.value();
+
188}
189
-
190#endif // RESULT_LIB
-
Err object represents an unsuccessful outcome and can be implicitly converted to a result.
Definition: result.h:28
-
Ok object represents a successful outcome and can be implicitly converted to a result.
Definition: result.h:59
-
result is a type that represents either success or failure.
Definition: result.h:88
+
190} // namespace res
+
191
+
192#endif // RESULT_LIB
+
Err object represents an unsuccessful outcome and can be implicitly converted to a result.
Definition: result.h:30
+
Ok object represents a successful outcome and can be implicitly converted to a result.
Definition: result.h:61
+
result is a type that represents either success or failure.
Definition: result.h:90

Friends