gimo v0.1.0
Loading...
Searching...
No Matches
AndThen.hpp
Go to the documentation of this file.
1// Copyright Dominic (DNKpp) Koepke 2025.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// https://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef GIMO_ALGORITHM_AND_THEN_HPP
7#define GIMO_ALGORITHM_AND_THEN_HPP
8
9#pragma once
10
11#include "gimo/Common.hpp"
12#include "gimo/Pipeline.hpp"
14
15#include <functional>
16#include <tuple>
17#include <type_traits>
18#include <utility>
19
20namespace gimo::detail::and_then
21{
22 template <typename Nullable, typename Action>
23 consteval Nullable* print_diagnostics()
24 {
25 if constexpr (!std::is_invocable_v<Action, value_result_t<Nullable>>)
26 {
27 static_assert(always_false_v<Nullable>, "The and_then algorithm requires an action invocable with the nullable's value.");
28 }
30 {
31 static_assert(always_false_v<Nullable>, "The and_then algorithm requires an action with a nullable return-type.");
32 }
33
34 return nullptr;
35 }
36
37 template <typename Nullable, typename Action>
38 using result_t = std::invoke_result_t<
39 Action,
40 value_result_t<Nullable>>;
41
42 template <typename Action, nullable Nullable>
43 [[nodiscard]]
44 constexpr result_t<Nullable, Action> on_value(Action&& action, Nullable&& opt)
45 {
46 return std::invoke(
47 std::forward<Action>(action),
48 detail::forward_value<Nullable>(opt));
49 }
50
51 template <typename Action, nullable Nullable, typename Next, typename... Steps>
52 [[nodiscard]]
53 constexpr auto on_value(
54 Action&& action,
55 Nullable&& opt,
56 Next&& next,
57 Steps&&... steps)
58 {
59 return std::invoke(
60 std::forward<Next>(next),
61 and_then::on_value(std::forward<Action>(action), std::forward<Nullable>(opt)),
62 std::forward<Steps>(steps)...);
63 }
64
65 template <typename Action, nullable Nullable>
66 [[nodiscard]]
67 constexpr result_t<Nullable, Action> on_null([[maybe_unused]] Action&& action, [[maybe_unused]] Nullable&& opt)
68 {
69 return detail::construct_empty<result_t<Nullable, Action>>();
70 }
71
72 template <typename Action, expected_like Expected>
73 [[nodiscard]]
74 constexpr result_t<Expected, Action> on_null([[maybe_unused]] Action&& action, Expected&& expected)
75 {
76 return detail::rebind_error<result_t<Expected, Action>, Expected>(expected);
77 }
78
79 template <typename Action, nullable Nullable, typename Next, typename... Steps>
80 [[nodiscard]]
81 constexpr auto on_null(Action&& action, Nullable&& opt, Next&& next, Steps&&... steps)
82 {
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)...);
86 }
87
88 struct traits
89 {
90 template <nullable Nullable, typename Action>
91 static constexpr bool is_applicable_on = requires {
93 };
94
95 template <typename Action, nullable Nullable, typename... Steps>
96 [[nodiscard]]
97 static constexpr auto on_value(Action&& action, Nullable&& opt, Steps&&... steps)
98 {
99 if constexpr (is_applicable_on<Nullable, Action>)
100 {
101 return and_then::on_value(
102 std::forward<Action>(action),
103 std::forward<Nullable>(opt),
104 std::forward<Steps>(steps)...);
105 }
106 else
107 {
108 return *and_then::print_diagnostics<Nullable, Action>();
109 }
110 }
111
112 template <typename Action, nullable Nullable, typename... Steps>
113 [[nodiscard]]
114 static constexpr auto on_null(Action&& action, Nullable&& opt, Steps&&... steps)
115 {
116 if constexpr (is_applicable_on<Nullable, Action>)
117 {
118 return and_then::on_null(
119 std::forward<Action>(action),
120 std::forward<Nullable>(opt),
121 std::forward<Steps>(steps)...);
122 }
123 else
124 {
125 return *and_then::print_diagnostics<Nullable, Action>();
126 }
127 }
128 };
129}
130
131namespace gimo
132{
133 namespace detail
134 {
135 template <typename Action>
136 using and_then_t = BasicAlgorithm<and_then::traits, std::remove_cvref_t<Action>>;
137 }
138
155 template <typename Action>
156 [[nodiscard]]
157 constexpr auto and_then(Action&& action)
158 {
159 using Algorithm = detail::and_then_t<Action>;
160
161 return Pipeline{std::tuple<Algorithm>{std::forward<Action>(action)}};
162 }
163}
164
165#endif
A composite object representing a sequence of monadic operations.
Definition Pipeline.hpp:30
Concept describing a type that can be used as a monad in the pipeline.
Definition Common.hpp:200
constexpr auto and_then(Action &&action)
Creates a pipeline step that applies a function returning a nullable type.
Definition AndThen.hpp:157
Definition AndThen.hpp:21
The central customization point for the library.
Definition Common.hpp:102