#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();
}