我有一个实现方法Door
的课程LockCheck()
和一个方法Stove
的课程BurnerCheck()
。我想要一个类House
作为构造函数参数Door::LockCheck
或Stove::BurnerCheck
以及给定函数的一组未知args。然后House
将存储函数及其args,以便稍后可以调用它们。例如,
auto stove = Stove();
auto stove_check = stove.BurnerCheck;
auto burner_args = std::make_tuple<bool, bool>(true, false);
auto house = House(burner_args, stove_check);
// do some other stuff...
house.check_safety(); // internally calls stove.BurnerCheck(burner_args)
班级House
“看起来像什么?”
到目前为止,我有,
template <typename ReturnType, typename... Args>
class House {
public:
House(Args... args, std::function<ReturnType(Args...)> func)
: input_args_(std::forward_as_tuple(args...)),
safety_func_(func) {}
};
private:
Args... input_args_; // Is this the correct declaration?
std::function<ReturnType(Args...)> safety_func_;
};
注意:
C ++ 11
我已经看到了相关的SO问题,例如reading the docs和this。
答案 0 :(得分:1)
您可以将所有参数存储为元组。然后,您可以通过将元组解压缩为函数参数来调用safety_func_
。可以使用std::apply直接在C ++ 17中完成解包。
template <typename ReturnType, typename... Args>
class House {
public:
House(Args... args, std::function<ReturnType(Args...)> func)
: input_args_(std::forward<Args>(args)...),
safety_func_(func) {}
// Require C++17
ReturnType call_safety() {
return std::apply(safety_func_, input_args_);
}
private:
std::tuple<Args...> input_args_;
std::function<ReturnType(Args...)> safety_func_;
};
对于纯C ++ 11元组解包解决方案,请参阅this post
答案 1 :(得分:1)
一些初步考虑。
1)如果您编写模板类House
template <typename ReturnType, typename... Args>
class House {
// ...
House(Args... args, std::function<ReturnType(Args...)> func)
: input_args_(std::forward_as_tuple(args...)),
safety_func_(func) {}
检查方法的参数是&#34;未知&#34; (并且,我想,不同于类型)你必须在定义House
个对象时知道这些参数,并且你有House
个House
类型{{1}对Door
的支票进行House
类型检查等等,并且(在C ++ 17之前)您无法声明{{1}对象只是作为
Stove
但你必须明确模板类型;
House
建议:您对检查方法的auto house = House(burner_args, stove_check);
不感兴趣(如果可以忽略它),请使House<void, bool, bool> house{burner_args, stove_check};
成为非模板类并为其创建可变参数模板构造函数;
ReturnType
2)如果你有一个带有一些固定参数和一个可变参数列表的模板函数/方法/构造函数,请将参数的可变参数列表放在 last 位置,这样编译器就可以推导出参数的可变参数列表,不需要显式。
所以前面的构造函数变为
House
3)据我所知,没有办法将指向实际方法的指针传递给函数o到变量;所以没有
class House
{
public:
template <typename ... Args, typename F>
House (Args ... as, F f)
并且没有 template <typename F, typename ... Args>
House (F f, Args ... as)
作为auto stove_check = stove.BurnerCheck;
构造函数的参数。
我知道这种问题的常用方法是传递对象(stove_check
)和指向类的House
方法的指针,而不是对象;
stove
现在构造函数变为
BurnerCheck
您可以将auto house { House(stove, &Stove::BurnerCheck, /* variadic args */) };
的{{1}}方法称为
template <typename T, typename M, typename ... Args>
House (T t, M m, Args ... as)
现在我建议的BurnerCheck()
类:一个stove
成员的类,在 (t.*m)(as...)
构造函数中初始化,带有捕获对象,指针方法和参数的lambda。
一个只调用该成员的House
方法。
以下内容
std::function<void(void)>
以下是一个完整的工作示例
House
如果您对检查方法返回的值感兴趣...我想您可以使check_safety()
只包含class House
{
private:
std::function<void(void)> fn;
public:
template <typename T, typename M, typename ... Args>
House (T t, M m, Args ... as) : fn{[=]{ (t.*m)(as...); }}
{ }
void check_safety ()
{ fn(); }
};
参数的模板类,并因此调整类。