gimo v0.1.0
Loading...
Searching...
No Matches
OrElse.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_OR_ELSE_HPP
7#define GIMO_ALGORITHM_OR_ELSE_HPP
8
9#pragma once
10
11#include "gimo/Common.hpp"
12#include "gimo/Pipeline.hpp"
14
15#include <concepts>
16#include <functional>
17#include <tuple>
18#include <type_traits>
19#include <utility>
20
21namespace gimo::detail::or_else
22{
23 template <typename Nullable, typename Action>
24 consteval Nullable* print_diagnostics()
25 {
26 if constexpr (!std::is_invocable_v<Action>)
27 {
28 static_assert(always_false_v<Nullable>, "The or_else algorithm requires an action invocable without any arguments.");
29 }
30 else if constexpr (!std::same_as<Nullable, std::invoke_result_t<Action>>)
31 {
32 static_assert(always_false_v<Nullable>, "The or_else algorithm requires an action returning the same nullable type.");
33 }
34
35 return nullptr;
36 }
37
38 template <typename Action, nullable Nullable>
39 [[nodiscard]]
40 constexpr std::remove_cvref_t<Nullable> on_value([[maybe_unused]] Action&& action, Nullable&& opt)
41 {
42 return std::forward<Nullable>(opt);
43 }
44
45 template <typename Action, nullable Nullable, typename Next, typename... Steps>
46 [[nodiscard]]
47 constexpr auto on_value(
48 [[maybe_unused]] Action&& action,
49 Nullable&& opt,
50 Next&& next,
51 Steps&&... steps)
52 {
53 return std::forward<Next>(next).on_value(
54 std::forward<Nullable>(opt),
55 std::forward<Steps>(steps)...);
56 }
57
58 template <typename Action, nullable Nullable>
59 [[nodiscard]]
60 constexpr std::remove_cvref_t<Nullable> on_null(Action&& action, [[maybe_unused]] Nullable&& opt)
61 {
62 return std::invoke(std::forward<Action>(action));
63 }
64
65 template <nullable Nullable, typename Action, typename Next, typename... Steps>
66 [[nodiscard]]
67 constexpr auto on_null(Action&& action, Nullable&& opt, Next&& next, Steps&&... steps)
68 {
69 return std::invoke(
70 std::forward<Next>(next),
71 or_else::on_null(std::forward<Action>(action), std::forward<Nullable>(opt)),
72 std::forward<Steps>(steps)...);
73 }
74
75 struct traits
76 {
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>>>;
82 };
83
84 template <typename Action, nullable Nullable, typename... Steps>
85 [[nodiscard]]
86 static constexpr auto on_value(Action&& action, Nullable&& opt, Steps&&... steps)
87 {
88 if constexpr (is_applicable_on<Nullable, Action>)
89 {
90 return or_else::on_value(
91 std::forward<Action>(action),
92 std::forward<Nullable>(opt),
93 std::forward<Steps>(steps)...);
94 }
95 else
96 {
97 return *or_else::print_diagnostics<Nullable, Action>();
98 }
99 }
100
101 template <typename Action, nullable Nullable, typename... Steps>
102 [[nodiscard]]
103 static constexpr auto on_null(Action&& action, Nullable&& opt, Steps&&... steps)
104 {
105 if constexpr (is_applicable_on<Nullable, Action>)
106 {
107 return or_else::on_null(
108 std::forward<Action>(action),
109 std::forward<Nullable>(opt),
110 std::forward<Steps>(steps)...);
111 }
112 else
113 {
114 return *or_else::print_diagnostics<Nullable, Action>();
115 }
116 }
117 };
118}
119
120namespace gimo
121{
122 namespace detail
123 {
124 template <typename Action>
125 using or_else_t = BasicAlgorithm<or_else::traits, std::remove_cvref_t<Action>>;
126 }
127
139 template <typename Action>
140 [[nodiscard]]
141 constexpr auto or_else(Action&& action)
142 {
143 using Algorithm = detail::or_else_t<Action>;
144
145 return Pipeline{std::tuple<Algorithm>{std::forward<Action>(action)}};
146 }
147}
148
149#endif
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