6#ifndef GIMO_ALGORITHM_OR_ELSE_HPP
7#define GIMO_ALGORITHM_OR_ELSE_HPP
21namespace gimo::detail::or_else
23 template <
typename Nullable,
typename Action>
24 consteval Nullable* print_diagnostics()
26 if constexpr (!std::is_invocable_v<Action>)
28 static_assert(always_false_v<Nullable>,
"The or_else algorithm requires an action invocable without any arguments.");
30 else if constexpr (!std::same_as<Nullable, std::invoke_result_t<Action>>)
32 static_assert(always_false_v<Nullable>,
"The or_else algorithm requires an action returning the same nullable type.");
38 template <
typename Action, nullable Nullable>
40 constexpr std::remove_cvref_t<Nullable> on_value([[maybe_unused]] Action&& action, Nullable&& opt)
42 return std::forward<Nullable>(opt);
45 template <
typename Action, nullable Nullable,
typename Next,
typename... Steps>
47 constexpr auto on_value(
48 [[maybe_unused]] Action&& action,
53 return std::forward<Next>(next).on_value(
54 std::forward<Nullable>(opt),
55 std::forward<Steps>(steps)...);
58 template <
typename Action, nullable Nullable>
60 constexpr std::remove_cvref_t<Nullable> on_null(Action&& action, [[maybe_unused]] Nullable&& opt)
62 return std::invoke(std::forward<Action>(action));
65 template <nullable Nullable,
typename Action,
typename Next,
typename... Steps>
67 constexpr auto on_null(Action&& action, Nullable&& opt, Next&& next, Steps&&... steps)
70 std::forward<Next>(next),
71 or_else::on_null(std::forward<Action>(action), std::forward<Nullable>(opt)),
72 std::forward<Steps>(steps)...);
77 template <nullable Nullable,
typename Action>
78 static constexpr bool is_applicable_on =
requires {
79 requires std::same_as<
80 std::remove_cvref_t<Nullable>,
81 std::remove_cvref_t<std::invoke_result_t<Action>>>;
84 template <
typename Action, nullable Nullable,
typename... Steps>
86 static constexpr auto on_value(Action&& action, Nullable&& opt, Steps&&... steps)
88 if constexpr (is_applicable_on<Nullable, Action>)
90 return or_else::on_value(
91 std::forward<Action>(action),
92 std::forward<Nullable>(opt),
93 std::forward<Steps>(steps)...);
97 return *or_else::print_diagnostics<Nullable, Action>();
101 template <
typename Action, nullable Nullable,
typename... Steps>
103 static constexpr auto on_null(Action&& action, Nullable&& opt, Steps&&... steps)
105 if constexpr (is_applicable_on<Nullable, Action>)
107 return or_else::on_null(
108 std::forward<Action>(action),
109 std::forward<Nullable>(opt),
110 std::forward<Steps>(steps)...);
114 return *or_else::print_diagnostics<Nullable, Action>();
124 template <
typename Action>
125 using or_else_t = BasicAlgorithm<or_else::traits, std::remove_cvref_t<Action>>;
139 template <
typename Action>
143 using Algorithm = detail::or_else_t<Action>;
145 return Pipeline{std::tuple<Algorithm>{std::forward<Action>(action)}};
A composite object representing a sequence of monadic operations.
Definition Pipeline.hpp:30
constexpr auto or_else(Action &&action)
Creates a pipeline step that handles the null/error case.
Definition OrElse.hpp:141
Definition AndThen.hpp:21