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