gimo v0.1.0
Loading...
Searching...
No Matches
Pipeline.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_PIPELINE_HPP
7#define GIMO_PIPELINE_HPP
8
9#pragma once
10
11#include "gimo/Common.hpp"
13
14#include <functional>
15#include <tuple>
16#include <type_traits>
17#include <utility>
18
19namespace gimo
20{
28 template <typename... Steps>
30 {
31 template <typename... Others>
32 friend class Pipeline;
33
34 public:
39 [[nodiscard]]
40 explicit constexpr Pipeline(std::tuple<Steps...> steps)
41 : m_Steps{std::move(steps)}
42 {
43 }
44
51 template <nullable Nullable>
52 constexpr auto apply(Nullable&& opt) &
53 {
54 return apply(*this, std::forward<Nullable>(opt));
55 }
56
60 template <nullable Nullable>
61 constexpr auto apply(Nullable&& opt) const&
62 {
63 return apply(*this, std::forward<Nullable>(opt));
64 }
65
69 template <nullable Nullable>
70 constexpr auto apply(Nullable&& opt) &&
71 {
72 return apply(std::move(*this), std::forward<Nullable>(opt));
73 }
74
78 template <nullable Nullable>
79 constexpr auto apply(Nullable&& opt) const&&
80 {
81 return apply(std::move(*this), std::forward<Nullable>(opt));
82 }
83
89 template <typename... SuffixSteps>
90 constexpr auto append(Pipeline<SuffixSteps...> suffix) const&
91 {
92 return append(*this, std::move(suffix.m_Steps));
93 }
94
98 template <typename... SuffixSteps>
99 constexpr auto append(Pipeline<SuffixSteps...> suffix) &&
100 {
101 return append(std::move(*this), std::move(suffix.m_Steps));
102 }
103
109 template <typename... SuffixSteps>
110 [[nodiscard]]
111 friend constexpr auto operator|(Pipeline const& prefix, Pipeline<SuffixSteps...> suffix)
112 {
113 return prefix.append(std::move(suffix));
114 }
115
119 template <typename... SuffixSteps>
120 [[nodiscard]]
121 friend constexpr auto operator|(Pipeline&& prefix, Pipeline<SuffixSteps...> suffix)
122 {
123 return std::move(prefix).append(std::move(suffix));
124 }
125
126 private:
127 std::tuple<Steps...> m_Steps{};
128
129 template <typename Self, typename Nullable>
130 [[nodiscard]]
131 static constexpr auto apply(Self&& self, Nullable&& opt)
132 {
133 return std::apply(
134 [&]<typename First, typename... Others>(First&& first, Others&&... steps) {
135 return std::invoke(
136 std::forward<First>(first),
137 std::forward<Nullable>(opt),
138 std::forward<Others>(steps)...);
139 },
140 std::forward<Self>(self).m_Steps);
141 }
142
143 template <typename Self, typename... SuffixSteps>
144 [[nodiscard]]
145 static constexpr auto append(Self&& self, std::tuple<SuffixSteps...>&& suffixSteps)
146 {
147 using Appended = Pipeline<Steps..., SuffixSteps...>;
148
149 return Appended{
150 std::tuple_cat(std::forward<Self>(self).m_Steps, std::move(suffixSteps))};
151 }
152 };
153
154 namespace detail
155 {
156 template <typename T>
157 struct is_pipeline
158 : public std::false_type
159 {
160 };
161
162 template <typename... Steps>
163 struct is_pipeline<Pipeline<Steps...>>
164 : public std::true_type
165 {
166 };
167 }
168
173 template <typename T>
174 concept pipeline = detail::is_pipeline<std::remove_cvref_t<T>>::value;
175
185 template <nullable Nullable, pipeline Pipeline>
186 [[nodiscard]]
187 constexpr auto apply(Nullable&& opt, Pipeline&& steps)
188 {
189 return std::forward<Pipeline>(steps).apply(std::forward<Nullable>(opt));
190 }
191
192 namespace detail
193 {
194 template <typename Nullable, typename ConstRefSource, typename... Steps>
195 struct is_processable_by_impl
196 : public std::bool_constant<0u == sizeof...(Steps)>
197 {
198 };
199
200 template <typename Nullable, typename ConstRefSource, typename First, typename... Rest>
201 requires applicable_to<Nullable, const_ref_like_t<ConstRefSource, First>>
202 struct is_processable_by_impl<Nullable, ConstRefSource, First, Rest...>
203 : public is_processable_by_impl<
204 std::invoke_result_t<const_ref_like_t<ConstRefSource, First>, Nullable>,
205 ConstRefSource,
206 Rest...>
207 {
208 };
209
210 template <typename Nullable, typename Pipeline, typename StepList = std::remove_cvref_t<Pipeline>>
211 struct is_processable_by;
212
213 template <typename Nullable, typename ConstRefSource, typename... Steps>
214 struct is_processable_by<Nullable, ConstRefSource, Pipeline<Steps...>>
215 : public is_processable_by_impl<Nullable, ConstRefSource, Steps...>
216 {
217 };
218 }
219
225 template <typename Nullable, typename Pipeline>
228 && detail::is_processable_by<Nullable, Pipeline>::value;
229}
230
231#endif
constexpr Pipeline(std::tuple< Steps... > steps)
Constructs a pipeline from a tuple of steps.
Definition Pipeline.hpp:40
friend constexpr auto operator|(Pipeline &&prefix, Pipeline< SuffixSteps... > suffix)
Appends the right-hand-side pipeline to the end of the left-hand-side pipeline.
Definition Pipeline.hpp:121
constexpr auto apply(Nullable &&opt) const &
Applies nullable input on the pipeline.
Definition Pipeline.hpp:61
constexpr auto append(Pipeline< SuffixSteps... > suffix) const &
Appends another pipeline to the end of this one.
Definition Pipeline.hpp:90
friend constexpr auto operator|(Pipeline const &prefix, Pipeline< SuffixSteps... > suffix)
Appends the right-hand-side pipeline to the end of the left-hand-side pipeline.
Definition Pipeline.hpp:111
constexpr auto apply(Nullable &&opt, Pipeline &&steps)
Applies nullable input on the pipeline.
Definition Pipeline.hpp:187
constexpr auto apply(Nullable &&opt) &&
Applies nullable input on the pipeline.
Definition Pipeline.hpp:70
constexpr auto apply(Nullable &&opt) const &&
Applies nullable input on the pipeline.
Definition Pipeline.hpp:79
constexpr auto append(Pipeline< SuffixSteps... > suffix) &&
Appends another pipeline to the end of this one.
Definition Pipeline.hpp:99
constexpr auto apply(Nullable &&opt) &
Applies nullable input on the pipeline.
Definition Pipeline.hpp:52
friend class Pipeline
Definition Pipeline.hpp:32
Concept describing a type that can be used as a monad in the pipeline.
Definition Common.hpp:200
Checks whether the given type is a specialization of gimo::Pipeline.
Definition Pipeline.hpp:174
Evaluates whether a Nullable type can be processed by the entire pipeline.
Definition Pipeline.hpp:226
Definition AndThen.hpp:21