Iros
 
Loading...
Searching...
No Matches
curry.h
Go to the documentation of this file.
1#pragma once
2
7#include "di/meta/callable.h"
9#include "di/meta/util.h"
10#include "di/types/integers.h"
11
13template<typename Self>
14struct Curry;
15
16template<typename F, usize max_arity_in = NumericLimits<usize>::max>
17struct CurryImpl : Curry<CurryImpl<F, max_arity_in>> {
19
20public:
21 constexpr static auto max_arity = max_arity_in;
22
23 CurryImpl() = default;
24
25 template<typename... Args>
26 requires(concepts::ConstructibleFrom<F, Args...>)
27 constexpr CurryImpl(InPlace, Args&&... args) : m_f(di::forward<Args>(args)...) {}
28
29 CurryImpl(CurryImpl const&) = default;
30 CurryImpl(CurryImpl&&) = default;
31
32 auto operator=(CurryImpl const&) -> CurryImpl& = delete;
33 auto operator=(CurryImpl&&) -> CurryImpl& = delete;
34
35 template<typename... Args>
36 requires(concepts::Invocable<F&, Args...> || concepts::Callable<Base&, Args...>)
37 constexpr auto operator()(Args&&... args) & -> decltype(auto) {
38 if constexpr (concepts::Invocable<F&, Args...>) {
39 return di::invoke(m_f, di::forward<Args>(args)...);
40 } else {
41 return this->Base::operator()(di::forward<Args>(args)...);
42 }
43 }
44
45 template<typename... Args>
46 requires(concepts::Invocable<F const&, Args...> || concepts::Callable<Base const&, Args...>)
47 constexpr auto operator()(Args&&... args) const& -> decltype(auto) {
48 if constexpr (concepts::Invocable<F const&, Args...>) {
49 return di::invoke(m_f, di::forward<Args>(args)...);
50 } else {
51 return this->Base::operator()(di::forward<Args>(args)...);
52 }
53 }
54
55 template<typename... Args>
56 requires(concepts::Invocable<F, Args...> || concepts::Callable<Base &&, Args...>)
57 constexpr auto operator()(Args&&... args) && -> decltype(auto) {
58 if constexpr (concepts::Invocable<F, Args...>) {
59 return di::invoke(di::move(m_f), di::forward<Args>(args)...);
60 } else {
61 return di::move(*this).Base::operator()(di::forward<Args>(args)...);
62 }
63 }
64
65 template<typename... Args>
66 requires(concepts::Invocable<F const &&, Args...> || concepts::Callable<Base const &&, Args...>)
67 constexpr auto operator()(Args&&... args) const&& -> decltype(auto) {
68 if constexpr (concepts::Invocable<F const&&, Args...>) {
69 return di::invoke(di::move(m_f), di::forward<Args>(args)...);
70 } else {
71 return di::move(*this).Base::operator()(di::forward<Args>(args)...);
72 }
73 }
74
75private:
76 F m_f {};
77};
78
79template<typename F>
80constexpr auto deduce_max_arity() {
81 if constexpr (requires { F::max_arity; }) {
82 return F::max_arity;
83 } else {
85 }
86}
87
88template<typename Self>
90 constexpr static auto max_arity() { return deduce_max_arity<Self>(); }
91
92 Curry() = default;
93
94 Curry(Curry const&) = default;
95 Curry(Curry&&) = default;
96
97 auto operator=(Curry const&) -> Curry& = delete;
98 auto operator=(Curry&&) -> Curry& = delete;
99
100 template<concepts::DecayConstructible... Args>
101 requires(concepts::ConstructibleFrom<Self, Self&> && sizeof...(Args) < max_arity())
102 constexpr auto operator()(Args&&... args) & {
103 return di::bind_front(static_cast<Self&>(*this), di::forward<Args>(args)...);
104 }
105
106 template<concepts::DecayConstructible... Args>
107 requires(concepts::ConstructibleFrom<Self, Self const&> && sizeof...(Args) < max_arity())
108 constexpr auto operator()(Args&&... args) const& {
109 return di::bind_front(static_cast<Self const&>(*this), di::forward<Args>(args)...);
110 }
111
112 template<concepts::DecayConstructible... Args>
113 requires(concepts::ConstructibleFrom<Self, Self &&> && sizeof...(Args) < max_arity())
114 constexpr auto operator()(Args&&... args) && {
115 return di::bind_front(static_cast<Self&&>(*this), di::forward<Args>(args)...);
116 }
117
118 template<concepts::DecayConstructible... Args>
119 requires(concepts::ConstructibleFrom<Self, Self const &&> && sizeof...(Args) < max_arity())
120 constexpr auto operator()(Args&&... args) const&& {
121 return di::bind_front(static_cast<Self const&&>(*this), di::forward<Args>(args)...);
122 }
123};
124
126 template<concepts::DecayConstructible F>
127 constexpr auto operator()(F&& function) const {
128 return CurryImpl<F> { in_place, di::forward<F>(function) };
129 }
130
131 template<concepts::DecayConstructible F, usize max_arity>
132 constexpr auto operator()(F&& function, Constexpr<max_arity>) const {
133 return CurryImpl<F, max_arity> { in_place, di::forward<F>(function) };
134 }
135};
136}
137
138namespace di::function {
139using curry_ns::Curry;
140constexpr inline auto curry = curry_ns::CurryFunction {};
141}
142
143namespace di {
144using function::curry;
145using function::Curry;
146}
Definition callable.h:9
Definition operations.h:11
Definition invoke.h:58
Definition curry.h:12
constexpr auto deduce_max_arity()
Definition curry.h:80
Definition as_bool.h:8
constexpr auto curry
Definition curry.h:140
Definition zstring_parser.h:9
constexpr auto bind_front(F &&f, Args &&... args)
Definition bind_front.h:68
constexpr auto invoke
Definition invoke.h:100
constexpr auto in_place
Definition in_place.h:8
constexpr auto operator()(F &&function, Constexpr< max_arity >) const
Definition curry.h:132
constexpr auto operator()(F &&function) const
Definition curry.h:127
static constexpr auto max_arity
Definition curry.h:21
CurryImpl(CurryImpl const &)=default
auto operator=(CurryImpl &&) -> CurryImpl &=delete
auto operator=(CurryImpl const &) -> CurryImpl &=delete
CurryImpl(CurryImpl &&)=default
Curry< CurryImpl< F, max_arity_in > > Base
Definition curry.h:18
constexpr CurryImpl(InPlace, Args &&... args)
Definition curry.h:27
Definition curry.h:89
auto operator=(Curry const &) -> Curry &=delete
Curry(Curry const &)=default
constexpr auto operator()(Args &&... args) &
Definition curry.h:102
static constexpr auto max_arity()
Definition curry.h:90
auto operator=(Curry &&) -> Curry &=delete
Definition numeric_limits.h:7
A wrapper for a constexpr value.
Definition core.h:77
Definition in_place.h:4