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++ 对象将模板化函数和参数保留为成员以便稍后调用 的相关文章

  • 检查两个数是否是彼此的排列?

    给定两个数字 a b 使得 1 例如 123 是 312 的有效排列 我也不想对数字中的数字进行排序 如果您指的是数字的字符 例如 1927 和 9721 则 至少 有几种方法 如果允许排序 一种方法是简单地sprintf将它们放入两个缓冲
  • 当我使用“control-c”关闭发送对等方的套接字时,为什么接收对等方的套接字不断接收“”

    我是套接字编程的新手 我知道使用 control c 关闭套接字是一个坏习惯 但是为什么在我使用 control c 关闭发送进程后 接收方上的套接字不断接收 在 control c 退出进程后 发送方的套接字不应该关闭吗 谢谢 我知道使用
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • 如何忽略“有符号和无符号整数表达式之间的比较”?

    谁能告诉我必须使用哪个标志才能使 gcc 忽略 有符号和无符号整数表达式之间的比较 警告消息 gcc Wno sign compare 但你确实应该修复它警告你的比较
  • 实时服务器上的 woff 字体 MIME 类型错误

    我有一个 asp net MVC 4 网站 我在其中使用 woff 字体 在 VS IIS 上运行时一切正常 然而 当我将 pate 上传到 1and1 托管 实时服务器 时 我得到以下信息 网络错误 404 未找到 http www co
  • Newtonsoft JSON PreserveReferences处理自定义等于用法

    我目前在使用 Newtonsoft Json 时遇到一些问题 我想要的很简单 将要序列化的对象与所有属性和子属性进行比较以确保相等 我现在尝试创建自己的 EqualityComparer 但它仅与父对象的属性进行比较 另外 我尝试编写自己的
  • 为什么#pragma optimize("", off)

    我正在审查一个 C MFC 项目 在某些文件的开头有这样一行 pragma optimize off 我知道这会关闭所有以下功能的优化 但这样做的动机通常是什么 我专门使用它来在一组特定代码中获得更好的调试信息 并在优化的情况下编译应用程序
  • 如果使用 SingleOrDefault() 并在数字列表中搜索不在列表中的数字,如何返回 null?

    使用查询正数列表时SingleOrDefault 当在列表中找不到数字时 如何返回 null 或像 1 这样的自定义值 而不是类型的默认值 在本例中为 0 你可以使用 var first theIntegers Cast
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • 如何返回 json 结果并将 unicode 字符转义为 \u1234

    我正在实现一个返回 json 结果的方法 例如 public JsonResult MethodName Guid key var result ApiHelper GetData key Data is stored in db as v
  • 在数据库中搜索时忽略空文本框

    此代码能够搜索数据并将其加载到DataGridView基于搜索表单文本框中提供的值 如果我将任何文本框留空 则不会有搜索结果 因为 SQL 查询是用 AND 组合的 如何在搜索 从 SQL 查询或 C 代码 时忽略空文本框 private
  • Github Action 在运行可执行文件时卡住

    我正在尝试设置运行google tests on a C repository using Github Actions正在运行的Windows Latest 构建过程完成 但是当运行测试时 它被卡住并且不执行从生成的可执行文件Visual
  • 如何将单个 char 转换为 int [重复]

    这个问题在这里已经有答案了 我有一串数字 例如 123456789 我需要提取它们中的每一个以在计算中使用它们 我当然可以通过索引访问每个字符 但是如何将其转换为 int 我研究过 atoi 但它需要一个字符串作为参数 因此 我必须将每个字
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • 在 Dynamics CRM 插件中访问电子邮件发件人地址

    我正在编写一个 Dynamics CRM 2011 插件 该插件挂钩到电子邮件实体的更新后事件 阶段 40 pipeline http msdn microsoft com en us library gg327941 aspx 并且在此阶
  • 32 位到 64 位内联汇编移植

    我有一段 C 代码 在 GNU Linux 环境下用 g 编译 它加载一个函数指针 它如何执行并不重要 使用一些内联汇编将一些参数推送到堆栈上 然后调用该函数 代码如下 unsigned long stack 1 23 33 43 save
  • Validation.ErrorTemplate 的 Wpf 动态资源查找

    在我的 App xaml 中 我定义了一个资源Validation ErrorTemplate 这取决于动态BorderBrush资源 我打算定义独特的BorderBrush在我拥有的每个窗口以及窗口内的不同块内
  • x86 上未对齐的指针

    有人可以提供一个示例 将指针从一种类型转换为另一种类型由于未对齐而失败吗 在评论中这个答案 https stackoverflow com questions 544928 reading integer size bytes from a
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob
  • 恢复上传文件控制

    我确实阅读了以下帖子 C 暂停 恢复上传 https stackoverflow com questions 1048330 pause resume upload in c 使用 HTTP 恢复上传 https stackoverflow

随机推荐

  • 在 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