@@ -53,6 +53,8 @@ class SentinelValue<T> {
5353// This means that Result will always contain an expected value.
5454// Therefore, if the user does not check if a function returned an error, an exception will NOT be
5555// thrown, and therefore the thread won't crash.
56+ // Constraint: requires at least 1 possible Error type
57+ // Constraint: Error types must inherit from ResultError
5658template <typename T, typename ... Errs>
5759 requires (sizeof ...(Errs) > 0) && (std::derived_from<Errs, ResultError> && ...)
5860class Result {
@@ -67,56 +69,45 @@ class Result {
6769
6870 // Construct a Result with a value and an error value.
6971 // Constraint: type T can be constructed from type U
70- // Constraint: some type in Errs can be constructed from type E
72+ // Constraint: E in Errs
7173 template <typename U, typename E>
72- requires std::constructible_from<T, U> && (std::constructible_from<E , Errs> || ...)
74+ requires std::constructible_from<T, U> && (std::same_as<std::remove_cvref<E> , Errs> || ...)
7375 constexpr Result (U&& value, E&& error)
7476 : value (std::forward<U>(value)),
7577 error (std::forward<E>(error)) {}
7678
7779 // Construct a Result with an error, initializing the normal value to its sentinel value.
7880 // Constraint: type T has a sentinel value
79- // Constraint: some type in Errs can be constructed from type U
80- // Constraint: type U can't be implicitly converted to type T
81- template <typename U>
82- requires Sentinel<T> && (std::constructible_from<U, Errs> || ...)
83- && (!std::convertible_to<U, T>)
84- constexpr Result (U&& error)
85- : error (std::forward<U>(error)),
86- value (sentinel_v<T>) {}
87-
88- // Construct a Result with an error, initializing the normal value to its sentinel value.
89- // Constraint: type T has a sentinel value
90- // Constraint: some type in Errs can be constructed from type U
91- template <typename U>
92- requires Sentinel<U> && (std::constructible_from<U, Errs> || ...)
93- explicit constexpr Result<U>(U&& error)
94- : error (std::forward<U>(error)),
81+ // Constraint: E in Errs
82+ template <typename E>
83+ requires Sentinel<T> && (std::same_as<std::remove_cvref<E>, Errs> || ...)
84+ constexpr Result (E&& error)
85+ : error (std::forward<E>(error)),
9586 value (sentinel_v<T>) {}
9687
9788 // Get the given error type, if it exists
98- // Constraint: some type Errs can be constructed from type U
99- template <typename U >
100- requires (std::same_as<U , Errs> || ...)
101- constexpr std::optional<U > get () const & {
89+ // Constraint: E in Errs
90+ template <typename E >
91+ requires (std::same_as<E , Errs> || ...)
92+ constexpr std::optional<E > get () const & {
10293 if (std::holds_alternative<std::monostate>(error)) {
10394 return std::nullopt ;
10495 } else {
105- return std::get<U >(error);
96+ return std::get<E >(error);
10697 }
107- };
98+ }
10899
109100 // Get the given error type, if it exists
110- // Constraint: some type Errs can be constructed from type U
111- template <typename U >
112- requires (std::same_as<U , Errs> || ...)
113- constexpr std::optional<U > get () && {
101+ // Constraint: E in Errs
102+ template <typename E >
103+ requires (std::same_as<E , Errs> || ...)
104+ constexpr std::optional<E > get () && {
114105 if (std::holds_alternative<std::monostate>(error)) {
115106 return std::nullopt ;
116107 } else {
117- return std::move (std::get<U >(error));
108+ return std::move (std::get<E >(error));
118109 }
119- };
110+ }
120111
121112 // get the normal value
122113 template <typename U = T>
@@ -155,43 +146,47 @@ class Result {
155146 T value;
156147};
157148
149+ // Result specialization for a value of type void, which would otherwise be impossible.
150+ // This specialization simply does not hold a "normal" value
151+ // Constraint: requires at least 1 possible Error type
152+ // Constraint: Error types must inherit from ResultError
158153template <typename ... Errs>
159154 requires (sizeof ...(Errs) > 0) && (std::derived_from<Errs, ResultError> && ...)
160155class Result<void, Errs...> {
161156 public:
162157 // construct with an error value
163- template <typename U >
164- requires (std::constructible_from<Errs, U > || ...)
165- constexpr Result (U && error)
166- : error (std::forward<U >(error)) {}
158+ template <typename E >
159+ requires (std::same_as<std::remove_cvref<E>, Errs > || ...)
160+ constexpr Result (E && error)
161+ : error (std::forward<E >(error)) {}
167162
168163 // construct with no error value
169164 constexpr Result ()
170165 : error (std::monostate ()) {}
171166
172167 // Get the given error type, if it exists
173- // Constraint: some type Errs can be constructed from type U
174- template <typename U >
175- requires (std::same_as<U , Errs> || ...)
176- constexpr std::optional<U > get () const & {
168+ // Constraint: E in Errs
169+ template <typename E >
170+ requires (std::same_as<E , Errs> || ...)
171+ constexpr std::optional<E > get () const & {
177172 if (std::holds_alternative<std::monostate>(error)) {
178173 return std::nullopt ;
179174 } else {
180- return std::get<U >(error);
175+ return std::get<E >(error);
181176 }
182- };
177+ }
183178
184179 // Get the given error type, if it exists
185- // Constraint: some type Errs can be constructed from type U
186- template <typename U >
187- requires (std::same_as<U , Errs> || ...)
188- constexpr std::optional<U > get () && {
180+ // Constraint: E in Errs
181+ template <typename E >
182+ requires (std::same_as<E , Errs> || ...)
183+ constexpr std::optional<E > get () && {
189184 if (std::holds_alternative<std::monostate>(error)) {
190185 return std::nullopt ;
191186 } else {
192- return std::move (std::get<U >(error));
187+ return std::move (std::get<E >(error));
193188 }
194- };
189+ }
195190
196191 std::variant<std::monostate, Errs...> error;
197192};
0 commit comments