本文介绍了C ++对象将模板化函数和args保留为成员,以供以后调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个实现方法 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 对象,并且您有不同的 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 其中的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保留为成员,以供以后调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 12:19