Simple-Utility v2.3.1
Loading...
Searching...
No Matches
Composition.hpp
Go to the documentation of this file.
1// Copyright Dominic Koepke 2019 - 2023.
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 SIMPLE_UTILITY_FUNCTIONAL_COMPOSITION_HPP
7#define SIMPLE_UTILITY_FUNCTIONAL_COMPOSITION_HPP
8
9#include <concepts>
10#include <functional>
11#include <tuple>
12#include <type_traits>
13
20
21namespace sl::functional
22{
36 template <class T>
38 && std::is_empty_v<T>;
39
47 template <composition_strategy CompStrategy, function FirstFn, function SecondFn, function... OtherFns>
49 {
50 public:
51 using CompositionStrategy = CompStrategy;
52
63 template <class FirstCTorArg, class SecondCTorArg, class... OtherCTorArgs>
64 requires std::constructible_from<FirstFn, FirstCTorArg>
65 && std::constructible_from<SecondFn, SecondCTorArg>
66 && (... && std::constructible_from<OtherFns, OtherCTorArgs>)
67 [[nodiscard]]
68 constexpr Composition(
69 FirstCTorArg&& firstArg,
70 SecondCTorArg&& secondArg,
71 OtherCTorArgs&&... otherArgs
72 ) noexcept(std::is_nothrow_constructible_v<FirstFn, FirstCTorArg>
73 && std::is_nothrow_constructible_v<SecondFn, SecondCTorArg>
74 && (... && std::is_nothrow_constructible_v<OtherFns, OtherCTorArgs>))
75 : m_Functions{
76 std::forward<FirstCTorArg>(firstArg),
77 std::forward<SecondCTorArg>(secondArg),
78 std::forward<OtherCTorArgs>(otherArgs)...
79 }
80 {
81 }
82
89 template <class... Args>
90 requires std::invocable<CompStrategy, std::tuple<const FirstFn&, const SecondFn&, const OtherFns&...>, Args...>
91 constexpr decltype(auto) operator ()(
92 Args&&... args
93 ) const & noexcept(std::is_nothrow_invocable_v<
94 CompStrategy,
95 std::tuple<const FirstFn&, const SecondFn&, const OtherFns&...>,
96 Args...>)
97 {
98 return std::invoke(CompStrategy{}, fns(), std::forward<Args>(args)...);
99 }
100
107 template <class... Args>
108 requires std::invocable<CompStrategy, std::tuple<FirstFn&, SecondFn&, OtherFns&...>, Args...>
109 constexpr decltype(auto) operator ()(
110 Args&&... args
111 ) & noexcept(std::is_nothrow_invocable_v<
112 CompStrategy,
113 std::tuple<FirstFn&, SecondFn&, OtherFns&...>,
114 Args...>)
115 {
116 return std::invoke(CompStrategy{}, fns(), std::forward<Args>(args)...);
117 }
118
125 template <class... Args>
126 requires std::invocable<CompStrategy, std::tuple<const FirstFn&&, const SecondFn&&, const OtherFns&&...>, Args...>
127 constexpr decltype(auto) operator ()(
128 Args&&... args
129 ) const && noexcept(std::is_nothrow_invocable_v<
130 CompStrategy,
131 std::tuple<const FirstFn&&, const SecondFn&&, const OtherFns&&...>,
132 Args...>)
133 {
134 return std::invoke(CompStrategy{}, std::move(*this).fns(), std::forward<Args>(args)...);
135 }
136
143 template <class... Args>
144 requires std::invocable<CompStrategy, std::tuple<FirstFn&&, SecondFn&&, OtherFns&&...>, Args...>
145 constexpr decltype(auto) operator ()(
146 Args&&... args
147 ) && noexcept(std::is_nothrow_invocable_v<
148 CompStrategy,
149 std::tuple<FirstFn&&, SecondFn&&, OtherFns&&...>,
150 Args...>)
151 {
152 return std::invoke(CompStrategy{}, std::move(*this).fns(), std::forward<Args>(args)...);
153 }
154
159 constexpr std::tuple<const FirstFn&, const SecondFn&, const OtherFns&...> fns() const & noexcept
160 {
161 return tuple::transform_elements(m_Functions, [](auto& t) -> const auto& { return t; });
162 }
163
168 constexpr std::tuple<FirstFn&, SecondFn&, OtherFns&...> fns() & noexcept
169 {
170 return tuple::transform_elements(m_Functions, [](auto& t) -> auto& { return t; });
171 }
172
177 constexpr std::tuple<const FirstFn&&, const SecondFn&&, const OtherFns&&...> fns() const && noexcept
178 {
179 return tuple::transform_elements(m_Functions, [](auto& t) -> const auto&& { return std::move(t); });
180 }
181
186 constexpr std::tuple<FirstFn&&, SecondFn&&, OtherFns&&...> fns() && noexcept
187 {
188 return tuple::transform_elements(m_Functions, [](auto& t) -> auto&& { return std::move(t); });
189 }
190
191 private:
193 std::tuple<FirstFn, SecondFn, OtherFns...> m_Functions;
194 };
195
200 template <class T>
202 : public std::false_type
203 {
204 };
205
211 template <composition_strategy CompositionStrategy, function... Fns>
212 struct is_composition<Composition<CompositionStrategy, Fns...>>
213 : public std::true_type
214 {
215 };
216
221 template <class T>
223
235 template <composition_strategy CompositionStrategy, class FirstFn, class SecondFn, class... OtherFns>
236 requires (std::same_as<unwrap_functional_t<FirstFn>, FirstFn>
237 && std::same_as<unwrap_functional_t<SecondFn>, SecondFn>
238 && (... && std::same_as<unwrap_functional_t<OtherFns>, OtherFns>))
239 [[nodiscard]]
240 constexpr auto make_composition(
241 FirstFn&& firstFn,
242 SecondFn&& secondFn,
243 OtherFns&&... otherFns
244 ) noexcept(std::is_nothrow_constructible_v<std::remove_cvref_t<FirstFn>, FirstFn>
245 && std::is_nothrow_constructible_v<std::remove_cvref_t<SecondFn>, SecondFn>
246 && (... && std::is_nothrow_constructible_v<std::remove_cvref_t<OtherFns>, OtherFns>))
247 {
248 constexpr auto as_tuple = Overloaded{
249 []<class T>(T&& fn)
250 requires is_composition_v<std::remove_cvref_t<T>>
251 && std::same_as<CompositionStrategy, typename std::remove_cvref_t<T>::CompositionStrategy>
252 {
253 return std::forward<T>(fn).fns();
254 },
255 []<class T>(T&& fn) { return std::forward_as_tuple(std::forward<T>(fn)); }
256 };
257
258 return std::apply(
259 [&]<class... Fns>(Fns&&... fns)
260 {
261 return Composition<CompositionStrategy, std::remove_cvref_t<Fns>...>{std::forward<Fns>(fns)...};
262 },
263 std::tuple_cat(
264 as_tuple(std::forward<FirstFn>(firstFn)),
265 as_tuple(std::forward<SecondFn>(secondFn)),
266 as_tuple(std::forward<OtherFns>(otherFns))...));
267 }
268
280 template <composition_strategy CompositionStrategy, class FirstFn, class SecondFn, class... OtherFns>
281 [[nodiscard]]
282 constexpr auto make_composition(
283 FirstFn&& firstFn,
284 SecondFn&& secondFn,
285 OtherFns&&... otherFns
286 ) noexcept(noexcept(make_composition<CompositionStrategy>(
287 forward_unwrapped<FirstFn>(firstFn),
288 forward_unwrapped<SecondFn>(secondFn),
289 forward_unwrapped<OtherFns>(otherFns)...)))
290 {
291 return make_composition<CompositionStrategy>(
292 forward_unwrapped<FirstFn>(firstFn),
293 forward_unwrapped<SecondFn>(secondFn),
294 forward_unwrapped<OtherFns>(otherFns)...);
295 }
296
300}
301
302#endif
#define SL_UTILITY_NO_UNIQUE_ADDRESS
Definition: Config.hpp:21
Functional type, composing multiple other functional types via the provided strategy.
Definition: Composition.hpp:49
constexpr Composition(FirstCTorArg &&firstArg, SecondCTorArg &&secondArg, OtherCTorArgs &&... otherArgs) noexcept(std::is_nothrow_constructible_v< FirstFn, FirstCTorArg > &&std::is_nothrow_constructible_v< SecondFn, SecondCTorArg > &&(... &&std::is_nothrow_constructible_v< OtherFns, OtherCTorArgs >))
Constructor forwarding the given args to the related functional member.
Definition: Composition.hpp:68
constexpr std::tuple< FirstFn &&, SecondFn &&, OtherFns &&... > fns() &&noexcept
Getter to the member functions.
Definition: Composition.hpp:186
constexpr std::tuple< FirstFn &, SecondFn &, OtherFns &... > fns() &noexcept
Getter to the member functions.
Definition: Composition.hpp:168
CompStrategy CompositionStrategy
Definition: Composition.hpp:51
constexpr std::tuple< const FirstFn &, const SecondFn &, const OtherFns &... > fns() const &noexcept
Getter to the member functions.
Definition: Composition.hpp:159
constexpr std::tuple< const FirstFn &&, const SecondFn &&, const OtherFns &&... > fns() const &&noexcept
Getter to the member functions.
Definition: Composition.hpp:177
Checks whether the T denotes an unqualified type.
Definition: stl_extensions.hpp:60
Determines whether the given type satisfies the requirements of a composition strategy.
Definition: Composition.hpp:37
Determines whether the given type satisfies the constraints of a function type.
Definition: BasicClosure.hpp:79
constexpr bool is_composition_v
Convenience constant, yielding the value of the is_composition trait.
Definition: Composition.hpp:222
constexpr auto make_composition(FirstFn &&firstFn, SecondFn &&secondFn, OtherFns &&... otherFns) noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< FirstFn >, FirstFn > &&std::is_nothrow_constructible_v< std::remove_cvref_t< SecondFn >, SecondFn > &&(... &&std::is_nothrow_constructible_v< std::remove_cvref_t< OtherFns >, OtherFns >))
Base factory overload, taking fully unwrapped functional objects and forwarding those to a newly crea...
Definition: Composition.hpp:240
constexpr auto transform_elements(Tuple &&tuple, Transform transform)
Applies the transform on each element of the given source tuple and returns the results as a new tupl...
Definition: Algorithm.hpp:44
Definition: Arithmetic.hpp:13
Helper invocable type which can hold an arbitrary amount of functions, from which the best match will...
Definition: Overloaded.hpp:26
Primary template, yielding false type.
Definition: Composition.hpp:203