Самый простой способ - использовать std::bind
для хранения аргументов.
#include <functional>
template <typename Ret>
class FunctionMenu {
public:
template <typename Ret, typename... Args>
explicit FunctionMenu(std::function<Ret(Args...)> func, Args... args)
: m_function{std::bind(func, std::move(args)...)} {}
auto run() { return m_function(); }
private:
std::function<Ret()> m_function;
};
template <typename Ret, typename... Args>
FunctionMenu(std::function<Ret(Args...)>, Args...)->FunctionMenu<Ret>;
Таким образом, аргументы хранятся внутри std::function
. Также возможно сохранить аргументы вручную в std::tuple
и распаковать их при вызове run()
.
#include <tuple>
template <typename Ret, typename... Args>
class FunctionMenu2 {
public:
template <typename Ret, typename... Args>
explicit FunctionMenu2(std::function<Ret(Args...)> func, Args... args)
: m_function{func}, m_args{std::move(args)...} {}
auto run() { return std::apply(m_function, m_args); }
private:
std::function<Ret(Args...)> m_function;
std::tuple<Args...> m_args;
};
template <typename Ret, typename... Args>
FunctionMenu2(std::function<Ret(Args...)>, Args...)
->FunctionMenu2<Ret, Args...>;
Второй подход позволяет вам легче получить доступ к аргументам (если требуется). Вот как использовать оба класса:
int main() {
std::function<int(float, int)> f = [](auto a, auto b) {
std::cout << a << std::endl;
std::cout << b << std::endl;
return 0;
};
FunctionMenu menu(f, 1.f, 200);
FunctionMenu2 menu2(f, 1.f, 200);
std::cout << menu.run() << std::endl;
std::cout << menu2.run() << std::endl;
return 0;
}