我有一个称为“菜单”的类,用于显示用户可以选择的选项。然后,用户选择一个选项,然后处理该值。但是,我有一个不显示任何内容的子类,而是仅接收带有可变数量参数的std :: function。
签名看起来像
template<class FuncRetTy, class... FuncArgs>
class FunctionMenu : public Menu;
理想情况下,我想保存一个具有以下形式的类成员:
std::function<FuncRetTy(FuncArgs...)> m_function;
我还想从构造函数中自动推断出所有类型并保存FuncArgs...
的值,这样,每次调用重写的“ run()
”方法时,这些值就可以通过此函数运行。在run()
内部,将调用m_function(/* FuncArgs values */)
。
欢迎提出任何想法。我正在将Visual Studio 2019与C ++ 17一起使用。
这是您想要的吗?
#include <functional>
#include <iostream>
template<class Ret, class... Args>
class FunctionMenu {
std::function<Ret(Args...)> m_function;
public:
FunctionMenu(std::function<Ret(Args...)> f) : m_function(f) {}
Ret run(Args... args) {
return f(args...);
}
};
template<class Ret, class... Args>
FunctionMenu(std::function<Ret(Args...)>)->FunctionMenu<Ret, Args...>;
int test(int i, double d) {
std::cout << i << ' ' << d << '\n';
return 0;
}
int main() {
std::function m = test;
FunctionMenu fm{m};
}
((由于它似乎不相关,所以我没有添加Menu基类)
最简单的方法是使用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;
}