@@ -211,7 +211,7 @@ template<typename... Ts>
211211struct all_same : std::true_type {};
212212
213213// special type that is ignored by the all_same trait
214- struct all_same_ignored_type {};
214+ struct ignored_type {};
215215
216216/* *
217217 * @brief Check whether all types in a pack are the same
@@ -221,8 +221,7 @@ struct all_same_ignored_type {};
221221 */
222222template <typename T, typename ... Ts>
223223struct all_same <T, Ts...> :
224- std::bool_constant<
225- ((std::is_same_v<T, Ts> || std::is_same_v<all_same_ignored_type, Ts>) && ...)> {};
224+ std::bool_constant<((std::is_same_v<T, Ts> || std::is_same_v<ignored_type, Ts>) && ...)> {};
226225
227226/* *
228227 * @brief Check whether all types in a pack are the same
@@ -239,7 +238,7 @@ struct first_type_that_satisfies {};
239238// Specialization: at least one type in the pack
240239template <typename Condition, typename T, typename ... Ts>
241240struct first_type_that_satisfies <Condition, T, Ts...> :
242- std::conditional_t <
241+ std::conditional <
243242 Condition::template value<T>, // Check condition for T
244243 std::type_identity<T>, // If true, use T
245244 first_type_that_satisfies<Condition, Ts...> // Otherwise, check rest
@@ -249,6 +248,18 @@ struct first_type_that_satisfies<Condition, T, Ts...> :
249248template <typename Condition, typename ... Ts>
250249using first_type_that_satisfies_t = typename first_type_that_satisfies<Condition, Ts...>::type;
251250
251+ template <typename F, typename ... Args>
252+ struct invoke_result {
253+ using type = ignored_type;
254+ };
255+
256+ template <typename F, typename ... Args>
257+ requires std::invocable<F, Args...>
258+ struct invoke_result <F, Args...> : std::invoke_result<F, Args...> {};
259+
260+ template <typename F, typename ... Args>
261+ using invoke_result_t = invoke_result<F, Args...>::type;
262+
252263} // namespace traits
253264
254265/* *
@@ -268,7 +279,7 @@ class Result {
268279 // or_else return type helper
269280 template <typename Self, typename F, typename E>
270281 using or_else_return_t =
271- std ::invoke_result_t <F, decltype ((std::get<E>(std::declval<Self>().error)))>;
282+ traits ::invoke_result_t <F, decltype ((std::get<E>(std::declval<Self>().error)))>;
272283
273284 // or_else invocable callable helper
274285 template <typename Self, typename F, typename E>
@@ -414,7 +425,7 @@ class Result {
414425 // if the callable is invocable
415426 or_else_return_t <Self, F, Errs>,
416427 // if the callable is not invocable
417- traits::all_same_ignored_type >...>
428+ traits::ignored_type >...>
418429 // the callable must return a Result or void if it is invocable with a given error
419430 // type
420431 && (std::conditional_t <
@@ -433,7 +444,7 @@ class Result {
433444 std::conditional_t <
434445 traits::is_result_v<or_else_return_t <Self, F, Errs>>,
435446 // if the return is a Result
436- std::is_same<T, typename or_else_return_t <Self, F, Errs>::value_type >,
447+ std::is_same<T, or_else_return_t <Self, F, Errs>>,
437448 // otherwise, if the return is not a Result
438449 std::true_type>,
439450 // otherwise, if the callable is not invocable
@@ -448,23 +459,37 @@ class Result {
448459 traits::is_result_v<CallableReturnType>,
449460 CallableReturnType,
450461 std::remove_cvref_t <Self>>;
462+
451463 // if there isn't an error, return the value
452464 if (!self.has_error ()) {
453- return std::forward<Self>(self).value ;
465+ return ReturnType (std::forward<Self>(self).value );
466+ }
467+
468+ if constexpr (std::same_as<void , CallableReturnType>) {
469+ return std::visit ([&f](auto && arg) -> ReturnType {
470+ // even though this condition is impossible, it's necessary. Otherwise the
471+ // compiler will compile a branch where f is invoked with an unsupported argument
472+ // type
473+ if constexpr (!or_else_invocable_v<Self, F, decltype ((arg))>
474+ || std::
475+ is_same_v<std::monostate, std::remove_cvref_t <decltype (arg)>>) {
476+ throw std::logic_error (" This exception is unreachable" );
477+ } else {
478+ std::invoke (f, std::forward<decltype (arg)>(arg));
479+ return std::forward<decltype (arg)>(arg);
480+ }
481+ }, std::forward<Self>(self).error );
454482 }
455- // if the callable returns void, then return this Result instance after invoking the
456- // callable
457483 return std::visit ([&f](auto && arg) -> ReturnType {
458484 // even though this condition is impossible, it's necessary. Otherwise the
459485 // compiler will compile a branch where f is invoked with an unsupported argument
460486 // type
461- if constexpr (!or_else_invocable_v<Self, F, decltype ((arg))>) {
487+ if constexpr (!or_else_invocable_v<Self, F, decltype ((arg))>
488+ || std::is_same_v<std::monostate, std::remove_cvref_t <decltype (arg)>>) {
462489 throw std::logic_error (" This exception is unreachable" );
463- } else if constexpr (std::same_as<ReturnType, void >) {
490+ } else {
464491 std::invoke (f, std::forward<decltype (arg)>(arg));
465492 return std::forward<decltype (arg)>(arg);
466- } else {
467- return std::invoke (f, std::forward<decltype (arg)>(arg));
468493 }
469494 }, std::forward<Self>(self).error );
470495 }
0 commit comments