@@ -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+ */
7781namespace traits {
7882
7983/* *
@@ -330,6 +334,18 @@ using or_else_return_t = invoke_result_t<F, decltype((std::get<E>(std::declval<R
330334template <typename R, typename F, typename E>
331335concept 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