#include <iostream>
#include <tuple>
#include <functional>
namespace helper
{
template <std::size_t... Ts>
struct index {};
template <std::size_t N, std::size_t... Ts>
struct gen_seq : gen_seq<N - 1, N - 1, Ts...> {};
template <std::size_t... Ts>
struct gen_seq<0, Ts...> : index<Ts...> {};
}
template <typename... Ts>
class Action_impl
{
private:
std::function<void (Ts...)> f;
std::tuple<Ts...> args;
public:
template <typename F>
Action_impl(F&& func, Ts&&... args)
: f(std::forward<F>(func)),
args(std::make_tuple(std::forward<Ts>(args)...))
{}
template <typename... Args, std::size_t... Is>
void func(std::tuple<Args...>& tup, helper::index<Is...>)
{
f(std::get<Is>(tup)...);
}
template <typename... Args>
void func(std::tuple<Args...>& tup)
{
func(tup, helper::gen_seq<sizeof...(Args)>{});
}
void act()
{
func(args);
}
};
template <typename F, typename... Args>
Action_impl<Args...> make_action(F&& f, Args&&... args)
{
return Action_impl<Args...>(std::forward<F>(f), std::forward<Args>(args)...);
}
int main()
{
auto add = make_action([] (int a, int b) { std::cout << a+b; }, 2, 3);
add.act();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHVwbGU+CiNpbmNsdWRlIDxmdW5jdGlvbmFsPgoKbmFtZXNwYWNlIGhlbHBlcgp7CiAgICB0ZW1wbGF0ZSA8c3RkOjpzaXplX3QuLi4gVHM+CiAgICBzdHJ1Y3QgaW5kZXgge307CgogICAgdGVtcGxhdGUgPHN0ZDo6c2l6ZV90IE4sIHN0ZDo6c2l6ZV90Li4uIFRzPgogICAgc3RydWN0IGdlbl9zZXEgOiBnZW5fc2VxPE4gLSAxLCBOIC0gMSwgVHMuLi4+IHt9OwoKICAgIHRlbXBsYXRlIDxzdGQ6OnNpemVfdC4uLiBUcz4KICAgIHN0cnVjdCBnZW5fc2VxPDAsIFRzLi4uPiA6IGluZGV4PFRzLi4uPiB7fTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lLi4uIFRzPgpjbGFzcyBBY3Rpb25faW1wbAp7CiAgICBwcml2YXRlOgogICAgICAgIHN0ZDo6ZnVuY3Rpb248dm9pZCAoVHMuLi4pPiBmOwogICAgICAgIHN0ZDo6dHVwbGU8VHMuLi4+IGFyZ3M7CiAgICBwdWJsaWM6CiAgICAgICAgdGVtcGxhdGUgPHR5cGVuYW1lIEY+CiAgICAgICAgQWN0aW9uX2ltcGwoRiYmIGZ1bmMsIFRzJiYuLi4gYXJncykKICAgICAgICAgICAgOiBmKHN0ZDo6Zm9yd2FyZDxGPihmdW5jKSksCiAgICAgICAgICAgICAgYXJncyhzdGQ6Om1ha2VfdHVwbGUoc3RkOjpmb3J3YXJkPFRzPihhcmdzKS4uLikpCiAgICAgICAge30KCiAgICAgICAgdGVtcGxhdGUgPHR5cGVuYW1lLi4uIEFyZ3MsIHN0ZDo6c2l6ZV90Li4uIElzPgogICAgICAgIHZvaWQgZnVuYyhzdGQ6OnR1cGxlPEFyZ3MuLi4+JiB0dXAsIGhlbHBlcjo6aW5kZXg8SXMuLi4+KQogICAgICAgIHsKICAgICAgICAgICAgZihzdGQ6OmdldDxJcz4odHVwKS4uLik7CiAgICAgICAgfQoKICAgICAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4gQXJncz4KICAgICAgICB2b2lkIGZ1bmMoc3RkOjp0dXBsZTxBcmdzLi4uPiYgdHVwKQogICAgICAgIHsKICAgICAgICAgICAgZnVuYyh0dXAsIGhlbHBlcjo6Z2VuX3NlcTxzaXplb2YuLi4oQXJncyk+e30pOwogICAgICAgIH0KCiAgICAgICAgdm9pZCBhY3QoKQogICAgICAgIHsKICAgICAgICAgICAgZnVuYyhhcmdzKTsKICAgICAgICB9Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRiwgdHlwZW5hbWUuLi4gQXJncz4KQWN0aW9uX2ltcGw8QXJncy4uLj4gbWFrZV9hY3Rpb24oRiYmIGYsIEFyZ3MmJi4uLiBhcmdzKQp7CiAgICByZXR1cm4gQWN0aW9uX2ltcGw8QXJncy4uLj4oc3RkOjpmb3J3YXJkPEY+KGYpLCBzdGQ6OmZvcndhcmQ8QXJncz4oYXJncykuLi4pOwp9CgppbnQgbWFpbigpCnsKICAgIGF1dG8gYWRkID0gbWFrZV9hY3Rpb24oW10gKGludCBhLCBpbnQgYikgeyBzdGQ6OmNvdXQgPDwgYStiOyB9LCAyLCAzKTsKCiAgICBhZGQuYWN0KCk7Cn0=