C++ 对象将模板化函数和参数保留为成员以便稍后调用

2024-04-11

我有课Door实现一个方法LockCheck(),和一个类Stove用一种方法BurnerCheck()。我想要上课House作为构造函数参数Door::LockCheck or Stove::BurnerCheck以及给定函数的一组未知参数。House然后将存储该函数及其参数,以便稍后可以调用它们。例如,

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_;
};

Notes:

  • C++11

  • 我已经看过相关的问题,例如this https://stackoverflow.com/questions/3534812/how-does-the-template-parameter-of-stdfunction-work-implementation and this https://stackoverflow.com/questions/20612774/stdfunction-as-template-parameter.


一些初步的考虑。

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参数并相应地调整类别。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 对象将模板化函数和参数保留为成员以便稍后调用 的相关文章

随机推荐

  • 在 Javascript 中将函数应用于 Null

    为什么以下工作有效 function sum a b return a b var result sum call null 3 4 7 为什么要定义结果 我调用 sum 作为 null 的方法 但 null 不是对象 不能有属性 到底是怎
  • 文件准备好澄清了吗?

    我最近看到一些使用这种模式的网站 这让我想到了一些陷阱
  • jquery中将多个数组合并为一个数组

    我正在尝试使用 jquery 将多个数组合并到一个数组 我知道我们可以使用 jquery merge 函数将两个数组合并为一个 我们也可以循环遍历这些数组并将它们连接到一个数组中 但我只是想知道是否有其他方法可以在不使用任何循环的情况下实现
  • IoC 容器本身的单元测试

    我认为以前没有人问过这个问题 尽管搜索这样的术语确实很困难单元测试ioc容器并且没有找到有关如何实现 IoC 以便执行单元测试的问题 我想对 IoC 容器本身进行单元测试 基本上是因为有时我会遇到容器问题 就像应用程序的任何其他部分一样 并
  • 使用类型提示时无法传递 null 参数

    以下代码 class Type function foo Type t foo null 运行时失败 PHP 致命错误 传递给 foo 的参数 1 不能为 null 为什么不允许像其他语言一样传递null PHP 7 1 或更高版本 201
  • 如何使用adb shell输入来输入&符号?

    adb shell input text 不起作用 也不行adb shell input keyevent KEYCODE AMPERSAND 相关问题 7789826 https stackoverflow com questions 7
  • Android约束布局水平划分

    我正在处理一个 Android 项目 我使用了ConstraintLayout 我想将布局设计为两个保持水平线的块 每个块将获得 50 的宽度 我怎样才能做到这一点ConstraintLayout 有两种方法可以做到这一点 使用链约束 使用
  • 如何在卡西欧 fx-991ES 计算器中计算 Mod b

    有谁知道如何在卡西欧 fx 991ES 计算器中计算 Mod b 谢谢 该计算器没有任何模函数 然而 有一种非常简单的方法可以使用显示模式来计算模数ab c 而不是传统的d c 如何切换显示模式ab c Go to settings Shi
  • 如何在 C# 中获取文件夹大小? [复制]

    这个问题在这里已经有答案了 可能的重复 如何在 C 中获取目录大小 目录中的文件 https stackoverflow com questions 1118568 how do i get a directory size files i
  • Itext 7 - PdfReader 未使用所有者密码打开错误

    I am using This example https developers itextpdf com content itext 7 jump start tutorial examples chapter 5 for the lat
  • 迭代数组时应该使用 for-of 还是 forEach? [复制]

    这个问题在这里已经有答案了 另外 这是风格问题还是功能问题 这是一个偏好问题还是一个更好 我试图理解 for of 的目的 通常我使用 let iterable 10 20 30 iterable forEach val gt consol
  • 将 WAV 文件转换为频谱图

    嗨 我对这件事很陌生 所以请耐心等待 我正在尝试将 WAV 文件转换为频谱图 但不确定如何开始 我读到一些内容 说要读取 PCM 数据 我认为是我的 WAV 文件 并将其存储在 WavReader 类的数组中 然后再对其应用 FFT 并将其
  • django:gettext 并强制转换为 unicode

    我的 Django 应用程序中有以下代码 class Status object def init self id desc self id id self desc desc def unicode self return self de
  • 将所有选定的项目从 ListView 复制到 ListView 2

    如何将多个项目从 ListView 复制到另一个 现在我正在这样做 procedure TForm1 CopyToRightClick Sender TObject var selected TListItem addItems TList
  • 主动调整主窗口内小部件的大小

    I have a few widgets in a main window i want the user to be able to resize the widgets inside the window as they please
  • 替换 DataColumn 中的值

    循环行时如何替换列值 我的数据表有两列 我想替换每一行第一列的值 我无法获取或设置列值 到目前为止 我只能访问 DefaultValue 和 ColumnName 等 即使创建新的 DataColumn 我也无法设置其值 感觉我在这里缺少一
  • 如何使用批处理文件从系统配置中删除环境变量

    我需要从客户端工作站中删除系统变量 我有 500 多个客户端 所以我想提供批处理文件给用户自己运行以删除系统变量 You may want to make these two permanent with setx but obviousl
  • 如何在Linux shell脚本中插入新行? [复制]

    这个问题在这里已经有答案了 我想在多个 echo 语句之间插入一个新行 我努力了echo hello n 但它不起作用 正在打印 n 我想要这样的期望输出 Create the snapshots Snapshot created 在之间插
  • 如何在不闪烁的情况下更新 Shiny 中的值?

    我每秒都会更新一个闪亮的文本输出 该文本输出是从 SQL 数据库读取的 这只需要一些时间 在仪表板中 我只想看看输出如何变化而没有花哨的动画 闪烁 是否可以在等待更新时删除动画并仅显示文本 这是一些代码示例 您可以在其中看到更新的闪烁 ui
  • C++ 对象将模板化函数和参数保留为成员以便稍后调用

    我有课Door实现一个方法LockCheck 和一个类Stove用一种方法BurnerCheck 我想要上课House作为构造函数参数Door LockCheck or Stove BurnerCheck以及给定函数的一组未知参数 Hous