Simple-Utility v2.3.1
Loading...
Searching...
No Matches
InvokePolicies.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_MIXIN_INVOKE_POLICIES_HPP
7#define SIMPLE_UTILITY_FUNCTIONAL_MIXIN_INVOKE_POLICIES_HPP
8
9#pragma once
10
11#include <concepts>
12#include <functional>
13#include <type_traits>
14#include <utility>
15
20
21namespace sl::functional::detail
22{
23 template <class T>
24 concept invoke_strategy = std::is_empty_v<T>;
25
26 template <concepts::unqualified Derived, invoke_strategy InvokeStrategy>
28 : public CRTPBase<Derived>
29 {
30 private:
31 using CRTPBase<Derived>::derived;
32
33 public:
34 template <class... Args>
35 requires std::invocable<InvokeStrategy, const Derived&, Args...>
36 constexpr decltype(auto) operator ()(
37 Args&&... args
38 ) const & noexcept(std::is_nothrow_invocable_v<InvokeStrategy, const Derived&, Args...>)
39 {
40 return std::invoke(InvokeStrategy{}, derived(), std::forward<Args>(args)...);
41 }
42
43 template <class... Args>
44 requires std::invocable<InvokeStrategy, Derived&, Args...>
45 constexpr decltype(auto) operator ()(Args&&... args) & noexcept(std::is_nothrow_invocable_v<InvokeStrategy, Derived&, Args...>)
46 {
47 return std::invoke(InvokeStrategy{}, derived(), std::forward<Args>(args)...);
48 }
49
50 template <class... Args>
51 requires std::invocable<InvokeStrategy, const Derived&&, Args...>
52 constexpr decltype(auto) operator ()(
53 Args&&... args
54 ) const && noexcept(std::is_nothrow_invocable_v<InvokeStrategy, const Derived&&, Args...>)
55 {
56 return std::invoke(InvokeStrategy{}, std::move(derived()), std::forward<Args>(args)...);
57 }
58
59 template <class... Args>
60 requires std::invocable<InvokeStrategy, Derived&&, Args...>
61 constexpr decltype(auto) operator ()(
62 Args&&... args
63 ) && noexcept(std::is_nothrow_invocable_v<InvokeStrategy, Derived&&, Args...>)
64 {
65 return std::invoke(InvokeStrategy{}, std::move(derived()), std::forward<Args>(args)...);
66 }
67 };
68
69 template <concepts::unqualified Derived, invoke_strategy InvokeStrategy>
71 : public CRTPBase<Derived>
72 {
73 private:
74 using CRTPBase<Derived>::derived;
75
76 public:
77 template <class... Args>
78 requires std::invocable<InvokeStrategy, const Derived&, Args...>
79 [[nodiscard]]
80 constexpr decltype(auto) operator ()(
81 Args&&... args
82 ) const & noexcept(std::is_nothrow_invocable_v<InvokeStrategy, const Derived&, Args...>)
83 {
84 return std::invoke(InvokeStrategy{}, derived(), std::forward<Args>(args)...);
85 }
86
87 template <class... Args>
88 requires std::invocable<InvokeStrategy, Derived&, Args...>
89 [[nodiscard]]
90 constexpr decltype(auto) operator ()(Args&&... args) & noexcept(std::is_nothrow_invocable_v<InvokeStrategy, Derived&, Args...>)
91 {
92 return std::invoke(InvokeStrategy{}, derived(), std::forward<Args>(args)...);
93 }
94
95 template <class... Args>
96 requires std::invocable<InvokeStrategy, const Derived&&, Args...>
97 [[nodiscard]]
98 constexpr decltype(auto) operator ()(
99 Args&&... args
100 ) const && noexcept(std::is_nothrow_invocable_v<InvokeStrategy, const Derived&&, Args...>)
101 {
102 return std::invoke(InvokeStrategy{}, std::move(derived()), std::forward<Args>(args)...);
103 }
104
105 template <class... Args>
106 requires std::invocable<InvokeStrategy, Derived&&, Args...>
107 [[nodiscard]]
108 constexpr decltype(auto) operator ()(
109 Args&&... args
110 ) && noexcept(std::is_nothrow_invocable_v<InvokeStrategy, Derived&&, Args...>)
111 {
112 return std::invoke(InvokeStrategy{}, std::move(derived()), std::forward<Args>(args)...);
113 }
114 };
115
116 struct InvocableStrategy
117 {
118 template <class Fn, class... Args>
119 requires std::invocable<unwrap_functional_t<Fn&&>, Args...>
120 [[nodiscard]]
121 constexpr std::invoke_result_t<unwrap_functional_t<Fn&&>, Args...> operator ()(
122 Fn&& fn,
123 Args&&... args
124 ) const noexcept(std::is_nothrow_invocable_v<unwrap_functional_t<Fn&&>, Args...>)
125 {
126 return std::invoke(
127 forward_unwrapped<Fn>(fn),
128 std::forward<Args>(args)...);
129 }
130 };
131
132 struct PredicateStrategy
133 {
134 template <class Fn, class... Args>
135 requires std::predicate<unwrap_functional_t<Fn&&>, Args...>
136 [[nodiscard]]
137 constexpr std::invoke_result_t<unwrap_functional_t<Fn&&>, Args...> operator ()(
138 Fn&& fn,
139 Args&&... args
140 ) const noexcept(std::is_nothrow_invocable_v<unwrap_functional_t<Fn&&>, Args...>)
141 {
142 return std::invoke(
143 forward_unwrapped<Fn>(fn),
144 std::forward<Args>(args)...);
145 }
146 };
147
148 struct ApplicableStrategy
149 {
150 template <class Fn, class Tuple>
151 requires concepts::applicable<unwrap_functional_t<Fn&&>, Tuple>
152 [[nodiscard]]
153 constexpr decltype(auto) operator ()(
154 Fn&& fn,
155 Tuple&& t
156 ) const noexcept(concepts::nothrow_applicable<unwrap_functional_t<Fn&&>, Tuple>)
157 {
158 return std::apply(
159 forward_unwrapped<Fn>(fn),
160 std::forward<Tuple>(t));
161 }
162 };
163}
164
165namespace sl::functional
166{
181 template <concepts::unqualified Derived>
182 using BasicInvokePolicy = detail::BasicInvokePolicy<Derived, detail::InvocableStrategy>;
183
188 template <concepts::unqualified Derived>
189 using NodiscardInvokePolicy = detail::NodiscardInvokePolicy<Derived, detail::InvocableStrategy>;
190
196 template <concepts::unqualified Derived>
197 using PredicateInvokePolicy = detail::NodiscardInvokePolicy<Derived, detail::PredicateStrategy>;
198
203 template <concepts::unqualified Derived>
204 using BasicApplyPolicy = detail::NodiscardInvokePolicy<Derived, detail::ApplicableStrategy>;
205
211 template <concepts::unqualified Derived>
212 using NodiscardApplyPolicy = detail::NodiscardInvokePolicy<Derived, detail::ApplicableStrategy>;
213
217}
218
219#endif
constexpr const Derived & derived() const noexcept
Up-casts the this pointer to a const lvalue reference to Derived.
Definition: CRTPBase.hpp:29
constexpr CRTPBase() noexcept
Default constructor, performing compile-time checks.
Definition: CRTPBase.hpp:47
detail::NodiscardInvokePolicy< Derived, detail::PredicateStrategy > PredicateInvokePolicy
CRTP type, enabling all four operator () overloads for derived classes, which are all marked with the...
Definition: InvokePolicies.hpp:197
detail::BasicInvokePolicy< Derived, detail::InvocableStrategy > BasicInvokePolicy
CRTP type, enabling all four operator () overloads for derived classes.
Definition: InvokePolicies.hpp:182
detail::NodiscardInvokePolicy< Derived, detail::ApplicableStrategy > NodiscardApplyPolicy
CRTP type, enabling all four operator () overloads for derived classes and expects the params to be t...
Definition: InvokePolicies.hpp:212
detail::NodiscardInvokePolicy< Derived, detail::InvocableStrategy > NodiscardInvokePolicy
CRTP type, enabling all four operator () overloads for derived classes, which are all marked with th ...
Definition: InvokePolicies.hpp:189
detail::NodiscardInvokePolicy< Derived, detail::ApplicableStrategy > BasicApplyPolicy
CRTP type, enabling all four operator () overloads for derived classes and expects the params to be t...
Definition: InvokePolicies.hpp:204
Definition: Arithmetic.hpp:13