Skip to content
This repository was archived by the owner on May 3, 2026. It is now read-only.

Commit 5af751d

Browse files
committed
remove fold expressions from Result::or_else requires clause
1 parent f48a1a0 commit 5af751d

1 file changed

Lines changed: 38 additions & 18 deletions

File tree

include/common/result.hpp

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ class ResultError {
7474
}
7575
};
7676

77+
/**
78+
* @brief Everything in the traits namespace is for internal use by the Result class only.
79+
*
80+
*/
7781
namespace traits {
7882

7983
/**
@@ -330,6 +334,18 @@ using or_else_return_t = invoke_result_t<F, decltype((std::get<E>(std::declval<R
330334
template<typename R, typename F, typename E>
331335
concept Invocable = std::invocable<F, decltype((std::get<E>(std::declval<R>().error)))>;
332336

337+
/**
338+
* @brief check whether a callable is invocable with any of the given argument types
339+
*
340+
* @note Result::or_else helper
341+
*
342+
* @tparam R the Result
343+
* @tparam F the callable
344+
* @tparam Es the possible argument types passed to the callable
345+
*/
346+
template<typename R, typename F, typename... Es>
347+
concept AnyInvocable = (Invocable<R, F, Es> || ...);
348+
333349
/**
334350
* @brief check whether a callable is invocable given the Result and argument type
335351
*
@@ -351,17 +367,19 @@ struct invocable_indirect_v {
351367
};
352368

353369
/**
354-
* @brief check whether a type is a Result or void.
370+
* @brief check whether the callable return types are all Result, ignored_type, or void
355371
*
356372
* @note helper for Result::or_else
357373
* @note concept is satisfied with ignored_type as well
358374
*
359-
* @tparam T the type to check
375+
* @tparam Ts the type to check
360376
*/
361-
template<typename T>
362-
concept ResultOrVoid =
363-
traits::IsResult<std::remove_cvref_t<T>> || std::same_as<void, std::remove_cvref_t<T>>
364-
|| std::same_as<ignored_type, std::remove_cvref_t<T>>;
377+
template<typename R, typename F, typename... Ts>
378+
concept AllResultOrVoid =
379+
((IsResult<or_else_return_t<R, F, Ts>>
380+
|| std::same_as<void, std::remove_cvref_t<or_else_return_t<R, F, Ts>>>
381+
|| std::same_as<ignored_type, std::remove_cvref_t<or_else_return_t<R, F, Ts>>>)
382+
&& ...);
365383

366384
/**
367385
* @brief check whether the value type of a Result is the other given type
@@ -370,11 +388,13 @@ concept ResultOrVoid =
370388
* @note concept if satisfied if T is void or ignored_type
371389
*
372390
* @tparam R the Result
373-
* @tparam T the other type
391+
* @tparam T the value type
374392
*/
375-
template<typename R, typename S>
376-
concept ValueTypeMatch = std::same_as<void, S> || std::same_as<ignored_type, S>
377-
|| std::same_as<typename S::value_type, typename S::value_type>;
393+
template<typename R, typename... Ts>
394+
concept AllValueTypeMatch =
395+
((std::same_as<void, Ts> || std::same_as<ignored_type, Ts>
396+
|| std::same_as<typename R::value_type, Ts>)
397+
&& ...);
378398

379399
} // namespace traits
380400

@@ -506,14 +526,14 @@ class Result {
506526
* @param f the callable
507527
*/
508528
template<typename Self, typename F>
509-
requires(traits::Invocable<Self, F, Errs> || ...)
510-
// the callable must always return the same type (if it's invocable)
511-
&& traits::AllSame<traits::or_else_return_t<Self, F, Errs>...>
512-
// the callable must return a Result or void (if it's invocable)
513-
&& (traits::ResultOrVoid<traits::or_else_return_t<Self, F, Errs>> && ...)
514-
// if the callable returns a Result, it must have the same value type as this
515-
// Result instance
516-
&& (traits::ValueTypeMatch<Self, traits::or_else_return_t<Self, F, Errs>> && ...)
529+
requires traits::AnyInvocable<Self, F, Errs...>
530+
// the callable must always return the same type (if it's invocable)
531+
&& traits::AllSame<traits::or_else_return_t<Self, F, Errs>...>
532+
// the callable must return a Result or void (if it's invocable)
533+
&& traits::AllResultOrVoid<Self, F, Errs...>
534+
// if the callable returns a Result, it must have the same value type as this
535+
// Result instance
536+
&& traits::AllValueTypeMatch<Self, traits::or_else_return_t<Self, F, Errs>...>
517537
constexpr auto or_else(this Self&& self, F&& f) {
518538
// the return type is the same as the return type of the callable, unless the callable
519539
// returns void. In that case, the return type is Self with cv-refs removed

0 commit comments

Comments
 (0)