一些初步的考虑。
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) {}
如果检查方法的参数是“未知的”(并且我想,不同类型的参数不同),您必须知道定义方法时的参数House
对象和你有不同的House
类型(一House
键入:Door
的支票,一张House
键入:Stove
的检查等)并且(在 C++17 之前)你不能声明House
对象简单地作为
auto house = House(burner_args, stove_check);
但你必须明确模板类型;某事作为
House<void, bool, bool> house{burner_args, stove_check};
建议:如果您对此不感兴趣ReturnType
检查方法(如果你可以忽略它)House
一个非模板类并为其创建一个可变模板构造函数;某事作为
class House
{
public:
template <typename ... Args, typename F>
House (Args ... as, F f)
2)如果您有一个带有一些固定参数和可变参数列表的模板函数/方法/构造函数,请将可变参数列表放在last位置,因此编译器可以从参数中推断出类型的可变列表,而无需显式地表示它。
所以前面的构造函数变成了这样
template <typename F, typename ... Args>
House (F f, Args ... as)
3)据我所知,没有办法将指向函数 o 的实际方法的指针传递给变量;所以不行
auto stove_check = stove.BurnerCheck;
and no stove_check
作为论点House
构造函数。
我知道解决此类问题的常用方法是传递对象(stove
)和一个指向BurnerCheck
方法引用的是类,而不是对象;某事作为
auto house { House(stove, &Stove::BurnerCheck, /* variadic args */) };
现在构造函数变成了
template <typename T, typename M, typename ... Args>
House (T t, M m, Args ... as)
你可以打电话给BurnerCheck()
的方法stove
as
(t.*m)(as...)
现在我的建议House
类:一个具有std::function<void(void)>
被初始化的成员,在House
构造函数,带有捕获对象、指针方法和参数的 lambda。
And a 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(); }
};
以下是一个完整的工作示例
#include <iostream>
#include <functional>
struct Door
{ void LockCheck (int, long) const { std::cout << "Door" << std::endl; } };
struct Stove
{ void BurnerCheck (char) const { std::cout << "Stove" << std::endl; } };
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(); }
};
int main ()
{
auto stove { Stove{} };
auto door { Door{} };
auto house1 { House{stove, &Stove::BurnerCheck, 'a'} };
auto house2 { House{door, &Door::LockCheck, 1, 2L} };
std::cout << "Some other stuff" << std::endl;
house1.check_safety();
house2.check_safety();
}
如果您对检查方法返回的值感兴趣...我想您可以House
一个模板类,只有ReturnType
参数并相应地调整类别。