20namespace gimo::detail::and_then
22 template <
typename Nullable,
typename Action>
23 consteval Nullable* print_diagnostics()
25 if constexpr (!std::is_invocable_v<Action, value_result_t<Nullable>>)
27 static_assert(always_false_v<Nullable>,
"The and_then algorithm requires an action invocable with the nullable's value.");
31 static_assert(always_false_v<Nullable>,
"The and_then algorithm requires an action with a nullable return-type.");
37 template <
typename Nullable,
typename Action>
38 using result_t = std::invoke_result_t<
40 value_result_t<Nullable>>;
42 template <
typename Action, nullable Nullable>
44 constexpr result_t<Nullable, Action> on_value(Action&& action, Nullable&& opt)
47 std::forward<Action>(action),
48 detail::forward_value<Nullable>(opt));
51 template <
typename Action,
nullable Nullable,
typename Next,
typename... Steps>
53 constexpr auto on_value(
60 std::forward<Next>(next),
61 and_then::on_value(std::forward<Action>(action), std::forward<Nullable>(opt)),
62 std::forward<Steps>(steps)...);
65 template <
typename Action, nullable Nullable>
67 constexpr result_t<Nullable, Action> on_null([[maybe_unused]] Action&& action, [[maybe_unused]] Nullable&& opt)
69 return detail::construct_empty<result_t<Nullable, Action>>();
72 template <
typename Action, expected_like Expected>
74 constexpr result_t<Expected, Action> on_null([[maybe_unused]] Action&& action, Expected&& expected)
76 return detail::rebind_error<result_t<Expected, Action>, Expected>(expected);
79 template <
typename Action,
nullable Nullable,
typename Next,
typename... Steps>
81 constexpr auto on_null(Action&& action, Nullable&& opt, Next&& next, Steps&&... steps)
83 return std::forward<Next>(next).on_null(
84 and_then::on_null(std::forward<Action>(action), std::forward<Nullable>(opt)),
85 std::forward<Steps>(steps)...);
90 template <nullable Nullable,
typename Action>
91 static constexpr bool is_applicable_on =
requires {
95 template <
typename Action,
nullable Nullable,
typename... Steps>
97 static constexpr auto on_value(Action&& action, Nullable&& opt, Steps&&... steps)
99 if constexpr (is_applicable_on<Nullable, Action>)
101 return and_then::on_value(
102 std::forward<Action>(action),
103 std::forward<Nullable>(opt),
104 std::forward<Steps>(steps)...);
108 return *and_then::print_diagnostics<Nullable, Action>();
112 template <
typename Action,
nullable Nullable,
typename... Steps>
114 static constexpr auto on_null(Action&& action, Nullable&& opt, Steps&&... steps)
116 if constexpr (is_applicable_on<Nullable, Action>)
118 return and_then::on_null(
119 std::forward<Action>(action),
120 std::forward<Nullable>(opt),
121 std::forward<Steps>(steps)...);
125 return *and_then::print_diagnostics<Nullable, Action>();