问题描述
我有一个实现方法 LockCheck()
的类 Door
和一个类使用方法
。我想要一个类 BurnerCheck()
的炉子 House
,将其作为构造函数参数 Door :: LockCheck
或 Stove :: BurnerCheck
以及给定函数的一组未知参数。然后, House
将存储该函数及其args,以便以后可以调用它们。例如,
I have a class Door
that implements a method LockCheck()
, and a class Stove
with a method BurnerCheck()
. I want a class House
that takes as a constructor argument either Door::LockCheck
or Stove::BurnerCheck
along with an unknown set of args for the given function. House
would then store the function and its args such that it can call them at some later time. For example,
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
C++11
我已经看到了相关的SO问题,例如和。
I've already seen related SO questions such as this and this.
推荐答案
有些
1)如果您编写模板类 House
1) If you write a template class 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) {}
其中check方法的参数是未知的(并且我认为,每个类型的类型都不相同),当您定义 House $ c时,您必须知道这些参数$ c>对象,并且您有不同的
House
类型(对于 Door,有一种
的支票,一种 House
类型 House
的类型,用于 Stove
的支票等)和(之前C ++ 17)您不能简单地声明 House
对象
where the argument of the check methods are "unknown" (and, I suppose, different from type to type) you have to know that arguments when you define the House
objects and you have different House
types (one House
type for Door
's checks, one House
type for Stove
's checks, etc.) and (before C++17) you can't declare House
object simply as
auto house = House(burner_args, stove_check);
,但是您必须明确模板类型;
but you have to explicit the template types; something as
House<void, bool, bool> house{burner_args, stove_check};
建议:您对 ReturnType $ c $不感兴趣c>其中的checks方法(如果可以忽略的话)使
House
成为非模板类,并为其创建可变参数的模板构造函数;
Suggestion: in you are not interested in the ReturnType
of the checks methods (and if you can ignore it) make House
a not-template class and make a variadic template constructor for it; something as
class House
{
public:
template <typename ... Args, typename F>
House (Args ... as, F f)
2)如果您有具有一些固定参数和可变参数列表的模板函数/方法/构造函数,将可变参数列表放置在 last 位置,以便编译器可以从参数推导可变类型列表,并且存在
2) If you have a template function/method/constructor with a some fixed arguments and a variadic list of arguments, place the variadic list of arguments in last position, so the compiler can deduce the variadic list of types from arguments and there is no need of explicit it.
因此,前面的构造函数变为
So the preceding constructor become something as
template <typename F, typename ... Args>
House (F f, Args ... as)
3)据我所知,无法将指向实际方法的指针传递给函数o的变量。所以不
3) As far I know, there is no way to pass a pointer to an actual method to a function o to a variable; so no
auto stove_check = stove.BurnerCheck;
并且没有 stove_check
作为<$的参数c $ c> House 构造函数。
and no stove_check
as argument of House
constructor.
我知道这种问题的通常方法是传递对象( stove
)和指向 BurnerCheck
方法的指针引用的是类,而不是对象;
The usual way that I know for this sort of problem is pass the object (stove
) and a pointer to BurnerCheck
method referred to the class, not to the object; something as
auto house { House(stove, &Stove::BurnerCheck, /* variadic args */) };
现在构造者变为
template <typename T, typename M, typename ... Args>
House (T t, M m, Args ... as)
调用炉灶
的 BurnerCheck()
方法为
(t.*m)(as...)
现在,我建议使用 House
类:具有 std :: function< void(void)>
成员的类在 House
构造函数中初始化,带有捕获对象,指针方法和参数的lambda。
Now my suggested House
class: a class with a std::function<void(void)>
member that is initialized, in House
constructor, with a lambda that capture object, pointer method and arguments.
和一个<$只是调用该成员的c $ c> 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();
}
如果您对从检查方法返回的值感兴趣...我想您可以仅使用 ReturnType
参数使 House
成为模板类,然后调整该类。
If you're interested in the value returned from the checked method... I suppose you can make House
a template class with only the ReturnType
parameter and adjust the class consequently.
这篇关于C ++对象将模板化函数和args保留为成员,以供以后调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!