C11 : 函数模板 std::function

2023-11-12

目录

std::function

定义

实现原理

应用

注意事项


std::function

定义

类模板 std::function 是一种通用的、多态的函数封装

std::function 的实例可以对任何可以调用的目标实体进行存储、复制和调用操作,这些目标实体包括普通函数、Lambda 表达式、函数指针以及其他函数对象等。

std::function 对象是对 C++ 中现有的可调用实体的一种类型安全的包裹(像函数指针这类可调用实体,是类型不安全的)。

通常 std::function 是一个函数对象类,它包装其它任意的函数对象,被包装的函数对象具有类型为 T1, ..., TN 的 N 个参数,并且返回一个可转换到 R 类型的值。std::function 使用模板转换构造函数接收被包装的函数对象;特别是,闭包类型可以隐式地转换为 std::function。

实现原理

  1. 通过类的多态,即通过虚表来达到多态;

  2. 通过 C 语言的函数指针来实现;

单参数类模板,是 function<int(int)> 或 function<String(int)> 等格式的类模板:

template<class R, typename Arg0>
class myfunction<R(Arg0)>
{
    public:
        R operator()(Arg0 arg0)
        {
            return ...;
        }   
}

若实现可以调用不同的函数,模板函数首先要有一个指针,而且该指针具有多态性(C++ 通过基继承和虚表),故需要有一个基类指针使得所有继承于该类的子类成员,使用 virtual 关键字创建虚表:

template<class R, typename Arg0>
class myfunction<R(Arg0)> function 
{
    private:
        class __callbase{
            public:
                virtual R operator()(Arg0 arg0) = 0;
                virtual ~__callbase(){ }
        };

        __callbase *base_;

    public:
        R operator()(Arg0 arg0){
            return (*__callbase)(arg0);
    }
};

实现子类:

class myfunction<R(Arg0)> function{
    private:
        template<typename F>
        class __callable : public __callbase {
            public:
                // 增加指向赋值给 function 类的函数指针或函数类对象
                callable(F functor)
                    : functor(functor){ }
                // 指向后重载操作符进行直接调用
                virtual R operatr()(Arg0 arg0){
                    return functor(arg0);
                }
            private:
                // 指向具体的函数或函数类对象,由模板推导
                F functor;
        };
    public:
        template<typename F>
        myfunction(F f):base_(new __callable<F>(f)){
        }

        ~myfunction(){
            if(base_){
                delete base_;
                base_ = nullptr;
            }
        }
};

应用

通过 std::function 对 C++ 中各种可调用实体(普通函数、Lambda 表达式、函数指针、 仿函数以及其它函数对象等)的封装,形成一个新的可调用的、统一的 std::function 对象。

#include <functional>
#include <iostream>
using namespace std;

std::function<int(int)> Functional;


int TestFunc(int a){ return a;}// 普通函数

auto lambdaFn = [](int a)->int{ return a; };// Lambda表达式

class Functor{ // 仿函数(functor)
 public:
    int operator()(int a){return a;}
};

class TestClass{
 public:
    int ClassMember(int a) { return a; }// 1.类成员函数
    static int StaticMember(int a) { return a; }// 2.类静态函数
}; 


int main()
{

    // 普通函数
    Functional = TestFunc;
    int result = Functional(10);
    cout << "普通函数:"<< result << endl;


    // Lambda表达式
    Functional = lambdaFn;
    result = Functional(20);
    cout << "Lambda表达式:"<< result << endl;


    // 仿函数
    Functor testFunctor;
    Functional = testFunctor;
    result = Functional(30);
    cout << "仿函数:"<< result << endl;

    // 类成员函数
    TestClass testObj;
    Functional = std::bind(&TestClass::ClassMember, testObj
                    , std::placeholders::_1);
    result = Functional(40);
    cout << "类成员函数:"<< result << endl;


    // 类静态函数
    Functional = TestClass::StaticMember;
    result = Functional(50);
    cout << "类静态函数:"<< result << endl;
    return 0;

}

注意事项

  • 关于可调用实体转换为 std::function 对象需要遵守以下两条原则:

    • 转换后的 std::function 对象的参数能转换为可调用实体的参数;

    • 可调用实体的返回值能转换为 std::function 对象的返回值。

  • std::function 对象最大的用处就是在实现函数回调,需要注意,它不能被用来检查相等或者不相等,但是可以与 NULL 或者 nullptr 进行比较

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

C11 : 函数模板 std::function 的相关文章

  • MongoDB C# 驱动程序检查身份验证状态和角色

    这是我使用 MongoDB 身份验证机制登录 MongoDB 的代码 try var credential MongoCredential CreateMongoCRCredential test admin 123456 var sett
  • C#中如何检测字符串是否为货币

    通常当我需要转换时currency string 如 1200 55 z 或 1 249 到十进制值我这样做 if currencyString Contains z decimal value Decimal Parse dataToCh
  • 从 SQL 数据库获取日期时间

    我的数据库表中有一个 DateTime 记录 我编写一个查询从数据库中获取它 string command2 select Last Modified from Company Data where Company Name Descrip
  • 测试 hdf5/c++ 中的组是否存在

    我正在打开一个现有的 HDF5 文件来附加数据 我想向那个叫做的小组保证 A存在以供后续访问 我正在寻找一种简单的方法来创建 A有条件地 如果不存在则创建并返回新组 或者返回现有组 一种方法是测试 A存在 我怎样才能高效地做到这一点 根据
  • 如何在 C# 事件中区分更改是由代码还是由用户进行?

    我有一个简单的TextBox一开始是空的 我有一个简单的事件 TextChanged 可以知道用户何时更改了其中的任何内容TextBox 但是 如果我自己在代码中对其执行任何操作 该事件就会触发 喜欢设置textbox Text Test
  • boost线程在中断时不打印退出消息

    我有这段代码用于执行三个线程 其中第二个线程应在按 Enter 时中断并打印退出消息 void input val DO STUFF return void process val DO STUFF try cout lt lt waiti
  • 实体框架代码优先 - 在另一个文件中配置

    使用 Fluent API 将表到实体的映射分开的最佳方法是什么 以便它全部位于单独的类中 而不是内联在 OnModelCreating 方法中 我目前在做什么 public class FooContext DbContext prote
  • 有没有比这更快的方法来查找目录和所有子目录中的所有文件?

    我正在编写一个程序 需要在目录及其所有子目录中搜索具有特定扩展名的文件 这将在本地驱动器和网络驱动器上使用 因此性能是一个问题 这是我现在使用的递归方法 private void GetFileList string fileSearchP
  • 字节到二进制字符串 C# - 显示所有 8 位数字

    我想在文本框中显示一个字节 现在我正在使用 Convert ToString MyVeryOwnByte 2 但是 当字节开头有 0 时 这些 0 就会被删除 例子 MyVeryOwnByte 00001110 Texbox shows g
  • 对数字进行向上和向下舍入 C++

    我试图让我的程序分别向上和向下舍入数字 例如 如果数字是3 6 我的程序应该四舍五入最接近的数字 4 如果该数字是3 4 它将向下舍入为 3 我尝试使用ceil库获取 3 个项目的平均值 results ceil marks1 marks2
  • 控制台应用程序 .net Core 2.0 的配置

    在 net Core 1 中我们可以这样做 IConfiguration config new ConfigurationBuilder AddJsonFile appsettings json true true Build 这样就可以使
  • 成员初始值设定项列表中的求值顺序是什么?

    我有一个带有一些参数的构造函数 我假设它们是按照列出的顺序初始化的 但在一种情况下 它们似乎是按相反的顺序初始化的 导致中止 当我反转参数时 程序停止中止 下面是我正在使用的语法的示例 a 之前需要初始化b 在这种情况下 你能保证这个初始化
  • 防止复制构造和返回值引用的分配

    如果我有一个函数返回对类实例的引用 但我无法控制其源 比如说list
  • 为什么以下代码不允许我使用 fgets 获取用户输入但可以使用 scanf?

    这是一个更大程序的简短摘录 但该程序的其余部分无关紧要 因为我认为我能够隔离该问题 我怀疑这与我使用 fgets 的方式有关 我读过 最好使用 fgets 而不是 scanf 但我似乎无法让它在这里正常工作 当我使用以下代码时 程序不会给我
  • 在 C# 中赋值后如何保留有关对象的信息?

    我一直在问我的想法可能是解决方案 https stackoverflow com questions 35254467 is it possible in c sharp to get the attributes attached to
  • 使用 Linq 进行异步Where过滤

    我有一个List通过填充的元素async调用 WebService 没问题 我需要过滤该列表以便在应用程序视图上显示某些内容 我试过这个 List
  • 如何使用 Clang 查找内存泄漏

    我在我的机器 ubuntu 中安装了 Clang 以便发现我的 C 代码中的内存泄漏 我编写了一个示例代码来检查它的工作情况 如下所示 File hello c for leak detection include
  • 编写专门用于类及其子类的函数模板

    我正在尝试编写一个函数模板 一个版本应该用于不满足另一版本标准的所有类型 当参数是给定类的基类或该类本身时 应使用另一个版本 我尝试过超载Base 但是当类派生自Base 他们使用通用的 而不是特定的 我也尝试过这种 SFINAE 方法 s
  • SSBO 是更大的 UBO?

    我目前正在 OpenGL 4 3 中使用 UBO 进行渲染 以将所有常量数据存储在 GPU 上 诸如材料描述 矩阵等内容 它可以工作 但是 UBO 的小尺寸 我的实现为 64kB 迫使我多次切换缓冲区 减慢渲染速度 我正在寻找类似的方法来存
  • 如何使用 g++ 在 c++ 20 中使用模块?

    我读了这个链接https gcc gnu org wiki cxx modules https gcc gnu org wiki cxx modules并尝试从该网站复制以下示例 我已经知道这个编译器部分支持模块系统 注 我用的是windo

随机推荐

  • 博客搭建(零):静态博客和动态博客的区别

    更好的阅读地址哦 静态博客 HTML CSS Javascript 优点 速度快 占用小 成本低 很安全 不易崩溃 易于抓取 缺点 无法支持原生评论 访问量统计 注册登录等功能 操作繁琐 上手难 网页内容固定 代码完全公开 日常维护繁琐 结
  • Ubuntu安装qt-opensource-linux-x64-5.11.1教程

    登陆qt官方下载页面 http download qt io archive qt 本文以安装qt opensource linux x64 5 11 1为例 把下载好的qt opensource linux x64 5 11 1 run放
  • node.js多版本管理nvm安装、切换、443问题等

    一 背景 线上环境出现问题 前端小哥本地编译不通过需要帮其看一下具体原因 由于我本地的node版本时16 3 0 项目编译需要v14 19 3 由于不同的项目支持的node版本不同 此时需要一个node多版本的管理工具 这是需要nvm管理n
  • 腾讯云直播工具类

    Maven 腾讯云直播
  • Port 1-1023

    Port Protocol 0 Reserved 1 TCPMUX TCP Port Service Multiplexer 2 Management Utility 3 Compression Process 4 5 Remote Job
  • LeetCode 剑指 Offer 34. 二叉树中和为某一值的路径

    输入一棵二叉树和一个整数 打印出二叉树中节点值的和为输入整数的所有路径 从树的根节点开始往下一直到叶节点所经过的节点形成一条路径 示例 给定如下二叉树 以及目标和 sum 22 5 4 8 11 13 4 7 2 5 1 返回 5 4 11
  • 刷题之轮转数组

    给你一个数组 将数组中的元素向右轮转 k 个位置 其中 k 是非负数 示例 1 输入 nums 1 2 3 4 5 6 7 k 3 输出 5 6 7 1 2 3 4 解释 向右轮转 1 步 7 1 2 3 4 5 6 向右轮转 2 步 6
  • 如何实现零宕机的配置热加载

    对于高可用的服务 为了保证服务可用性 更新配置时必然不能直接停止服务 可以使用配置热加载来避免服务暂停 不需要重启服务 配置的热加载可以分为两个场景 手动更新与自动更新 手动更新 对于一些临时调试 服务数量不多的情况下 可以进行手动更新配置
  • 外包干了2个月,技术退步明显.......

    先说一下自己的情况 大专生 18年通过校招进入武汉某软件公司 干了接近4年的功能测试 今年年初 感觉自己不能够在这样下去了 长时间呆在一个舒适的环境会让一个人堕落 而我已经在一个企业干了四年的功能测试 已经让我变得不思进取 谈了2年的女朋友
  • 【Tensorflow2.0】11、经典图像CNN模型实现代码

    文章目录 1 Lenet5 2 AlexNet 3 VGG 4 Inception系列 v1到v4 4 1 Inceptionv1 GoogLeNet 4 2 inceptionv2 4 3 inceptionv3 4 4 Inceptio
  • Android快速开发框架-ZBLibrary 源码分享

    坐标标准库ZBLibrary 是一个MVP架构的Android快速开发框架 提供一套开发标准 UI Data Listener 以及模板和工具类并规范代码 封装层级少 简单高效兼容性好 一句代码就可实现全局滑动返回 可重写 集成方便快捷的照
  • matlab练习程序(c/c++调用matlab

    这里的环境是windows7 vs2010 matlabR2010b 上一篇是通过engine来调用matlab中的语句 本篇是通过调用m文件编译成的h lib dll文件而实现的 首先写一个函数mysvd m function s v d
  • docker国内镜像加速

    1 阿里云容器 生成自己的加速地址 登陆地址 https cr console aliyun com 选择自己的系统 2 修改配置文件 针对Docker客户端版本大于 1 10 0 的用户 您可以通过修改daemon配置文件 etc doc
  • Linux防火墙

    安全防御 常见的攻击手段 拒绝服务 已知漏洞 口令破解 欺骗用户 常见的安全防御设备 基础类防火墙 IDS类 入侵检测系统 提供报告 事后分析 IPS类 入侵防御系统 针对数据包分析 根据模式匹配 阻断非法访问 主动安全类 什么是防火墙 工
  • 这篇文章带你读懂IP地址

    这篇文章带你读懂IP地址 一 IP地址介绍 二 IP地址分类及表示 三 IP地址的主要特点 四 特殊IP地址及私有IP地址 一 IP地址介绍 IP地址 全世界唯一的32位 4字节标识符 标识路由器主机的接口 IP地址 lt 网络号 gt l
  • 【Git CMD】Git上传本地代码到远程仓库(6步到位)

    步骤 1 创建指定名称的分支并切换至该分支 2 添加文件到暂存区 3 查看本地仓库和暂存区的状态 4 提交文件到本地仓库 5 查看本地仓库提交的历史 6 将本地当前分支推送到与本地当前分支同名的远程分支 1 创建指定名称的分支并切换至该分支
  • 学习PGL课程:图卷积网络GCN、图注意力网络GAT

    一 GCN 什么是图卷积 不同的地方在于 图像像素点周围的像素个数通常是固定的 而图结构上某个节点周围的节点数是不固定的 图卷积网络计算公式 1 邻接矩阵解释 2 度矩阵 表示节点与之相连节点的个数 包括自环 3 H l 表示第l次迭代的节
  • 具体项目下解决Echarts多端同步开发和维护的问题

    具体问题场景 PC端和移动端需要同时上线图表功能 没有多余工时 之后的版本迭代 功能 样式 配置等 默认双端同步 开发人员只希望维护一套代码 Echarts在移动端有部分功能不兼容不支持 Echarts在移动端的坑 移动端页面使用echar
  • Raspberry Pi使用TinyML运动识别

    我们将使用机器学习来构建在微型微控制器RP2040上运行的手势识别系统 探索Raspberry Pi Pico及其SDK Raspberry Pi Pico是具有灵活数字接口的低成本 高性能微控制器板 主要功能包括 Raspberry Pi
  • C11 : 函数模板 std::function

    目录 std function 定义 实现原理 应用 注意事项 std function 定义 类模板 std function 是一种通用的 多态的函数封装 std function 的实例可以对任何可以调用的目标实体进行存储 复制和调用