- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
template<typename F, typename... CurryArgs>
struct curry {
F func;
std::tuple<CurryArgs...> tup{};
curry(F f) : func(std::move(f)) {}
template<typename... CtorArgs>
curry(F f, CtorArgs &&... args) : func(std::move(f)), tup(std::forward<CtorArgs>(args)...) {}
template<typename Tup1, typename Tup2>
curry(F f, Tup1 && tup1, Tup2 && tup2) : func(std::move(f)), tup(std::tuple_cat(tup1, tup2)) {}
template<typename... Args>
auto operator()(Args &&... args)
{
constexpr size_t have_args = sizeof...(Args) + sizeof...(CurryArgs);
constexpr size_t need_args = detail::functor_traits<F>::args_count;
if constexpr (have_args > need_args) {
static_assert(!sizeof(std::tuple_element_t<0, std::tuple<Args...>>*),
"Too many arguments.");
} else if constexpr (have_args == need_args) {
return std::apply(func, std::tuple_cat(tup, std::tuple(std::forward<Args>(args)...)));
} else {
return curry<decltype(func), CurryArgs..., Args...>(func, tup, std::tuple(std::forward<Args>(args)...));
}
}
};
int main()
{
auto f = [](int a, float b, const std::string & c) -> int {
std::cout << "Functor! a = " << a << ", b = " << b << ", c = " << c << std::endl;
return a + static_cast<int>(b);
};
std::cout << f(16, 42.1f, "Hello") << std::endl;
auto c0 = curry(f);
auto c1 = c0(16);
auto c2 = c1(42.1f);
c0(16)(42.1f)("Hello");
c1(42.1f)("Hello");
c2("Hello");
c0(16, 42.1f)("Hello");
c0(16, 42.1f, "Hello");
c1(42.1f, "Hello");
}
Каррировали-каррировали, да выкаррировали.
https://wandbox.org/permlink/LPXFUNpWOREcB3wH