#include #include #if __cplusplus > 202002L template constexpr int sum(std::tuple vs) { return [&](std::index_sequence) { return (std::get(vs) + ...); } (std::index_sequence_for{}); } int basic_sum() { // return sum(std::tuple{0, 1, 2, 3}); int i{}; return sum(std::tuple{i++, i++, i++, i++}); } template struct curry { using tuple_t = std::tuple; tuple_t vs; curry(Ts&&... ts) : vs(std::forward(ts)...) {} curry(tuple_t&& t) : vs(std::move(t)) {} template constexpr auto operator()(U&& u) const noexcept -> curry { return {std::tuple_cat(vs, std::forward_as_tuple(std::forward(u)))}; } template constexpr auto apply(F&& f) -> decltype(auto) { return std::apply(f, vs); } }; template auto get(const curry& b) -> std::tuple_element_t>& { return std::get(b.vs); } template constexpr int add(curry vs) { return [&](std::index_sequence) { return (get(vs) + ...); } (std::index_sequence_for{}); } int build_sum() { // return add(build(1)(2)(3)); int i{}; return add(curry(i++)(i++)(i++)(i++)); } template typename Class> struct is_instantiation_of_impl : std::false_type {}; template typename Class> struct is_instantiation_of_impl, Class> : std::true_type {}; template typename Class> concept is_instantiation_of = is_instantiation_of_impl::value; template constexpr auto add(Ts... ts) requires(sizeof...(Ts) > 1 or (not is_instantiation_of && ...)) { return (ts + ... + 0); } int apply_sum() { int i{}; return curry(i++)(i++)(i++)(i++).apply( [](auto... ts) { return add(ts...); }); } #endif