C++中invoke与function的区别

news/2024/7/7 19:05:15

C++ invoke

invoke是C++17标准引入的一个函数模板,用来调用可调用对象(Callable Object,如函数指针、函数对象、成员函数指针等)并返回结果。

invoke提供了统一的调用语法,无论可调用对象的类型是什么,都可以使用同一种方式进行调用。

详见:https://en.cppreference.com/w/cpp/utility/functional/invoke

图片

在C++17之前,调用不同类型的可调用对象需要使用不同的语法,比如直接调用函数、使用类对象的运算符重载操作符()来调用函数对象、使用成员函数指针来调用类成员函数等等。这些调用方式虽然能用,但是不够灵活,而invoke解决了这种不一致的问题。

invoke函数的实现原理是通过使用SFINAE(Substitution Failure Is Not An Error)技术来判断可调用对象的类型,并根据类型调用对应的调用方式。因此,无论可调用对象的类型是什么,都可以使用invoke函数来调用,而不需要使用不同的语法。

它的实现原理可以看https://en.cppreference.com/w/cpp/utility/functional/invoke

下面是invoke的示例代码:

#include <iostream>
#include <functional>

void foo(int a, int b)
{
    std::cout << "a + b = " << a + b << std::endl;
}

class Bar
{
public:
    void operator()(int a, int b)
{
        std::cout << "a - b = " << a - b << std::endl;
    }
};

int main()
{
    int a = 10, b = 5;
    std::invoke(foo, a, b); // 调用普通函数
    Bar bar;
    std::invoke(bar, a, b); // 调用函数对象
    std::invoke(&Bar::operator(), bar, a, b); // 调用成员函数
    std::function<void(int, int)> f = foo;
    std::invoke(f, a, b); // 调用std::function对象
    return 0;
}

总结:std::invoke 提供了一种通用的函数调用语法,可以方便地调用各种可调用对象。

function与invoke的区别

std::function和std::invoke是两个不同的东西,功能也不同。std::function是一个函数对象的封装器,可以用来封装任意类型的可调用对象,比如函数指针、lambda表达式等,而 std::invoke 则是一个函数模板,用于在统一的接口下调用可调用对象。

比如,我们可以使用std::function来存储一个函数指针:

#include <functional>
#include <iostream>

void foo(int a, int b)
{
    std::cout << "foo(" << a << ", " << b << ")" << std::endl;
}

int main()
{
    std::function<void(int, int)> f = foo;
    f(1, 2);
}

上述代码中,我们将函数指针foo封装成了一个std::function对象f,然后通过调用f(1, 2)来调用函数foo

std::invoke的作用是提供一种通用的函数调用语法,可以用统一的方式来调用各种可调用对象,而不必关心它们具体是什么类型。

比如,可以使用std::invoke来调用一个东西,无论这个东西是函数指针、函数对象还是成员函数指针:

#include <functional>
#include <iostream>

void foo(int a, int b)
{
    std::cout << "foo(" << a << ", " << b << ")" << std::endl;
}

class Bar {
public:
    void bar(int a, int b) const
{
        std::cout << "Bar::bar(" << a << ", " << b << ")" << std::endl;
    }
};

int main()
{
    std::invoke(foo, 1, 2);

    Bar b;
    std::invoke(&Bar::bar, &b, 1, 2);
}

上面代码,使用std::invoke分别调用了函数foo和类Bar的成员函数bar,并传递了相应的参数。

总结,std::functionstd::invoke的使用场景是不同的。std::function 适用于需要存储可调用对象的场景,而std::invoke则适用于统一调用各种不同类型的可调用对象的场景。


http://lihuaxi.xjx100.cn/news/1723447.html

相关文章

C++的复杂,C是原罪:从值类别说开去

&#x1f449;导读 我们知道 C 的值类别包括左值、右值、纯右值、广义左值、将亡值。可 C 到底是经历了什么才硬要把这件事情搞得如此复杂呢&#xff1f;我们不妨从 C 语言、汇编和 C 设计发展的角度来分析一下这个问题~ &#x1f449;目录 0 写在前面 1 从 C 语言开始讲起 2 考…

C++之C++11字符串字面量后缀总结(二百四十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

ES6新特性:变量的解构赋值

文章目录 1 数组的解构赋值1.1 基本用法1.2 交换变量的值1.3 注意事项 2 对象的解构赋值2.1 基本用法2.2 属性重命名2.3 注意事项 ES6允许按照一定模式&#xff0c;从数组和对象中提取值&#xff0c;对变量进行赋值&#xff0c;这被称为解构&#xff08;Destructuring&#xff…

stable-diffusion-webui环境部署

stable-diffusion-webui环境部署 1. 环境创建2. 安装依赖库3.下载底模4.运行代码5. 报错信息报错1报错2 1. 环境创建 创建虚拟环境 conda create -n env_stable python3.10.0进入虚拟环境 conda activate env_stableclone源码 git clone https://github.com/AUTOMATIC1111/stab…

Zabbix监控IP地址是否畅通

一、fping安装 1.下载fping安装包 wget http://www.fping.org/dist/fping-4.0.tar.gz下载失败的&#xff0c;请看 https://download.csdn.net/download/qq_45748758/88477979 资源包已上传&#xff0c;免费 2.解压安装包 tar -xf fping-4.0.tar.gz3.安装 cd fping-4.0 ./c…

SSL证书对于SEO优化的重要性

在当今时代&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;对于企业和网站来说是至关重要的。而SSL证书在SEO优化中起着重要的作用。SSL证书是一种用于加密数据传输的安全协议&#xff0c;它为网站提供了安全连接&#xff0c;使用户可以放心地与网站进行交互。 首先&…

pk答题小程序怎么做?功能有哪些?为您揭秘!

“微信答题小程序&#xff08;仿头脑王者源码&#xff09;在线教育考试pk答题小程序”是一款专业性的答题小程序&#xff08;软著登记号&#xff1a;4078210号&#xff09;&#xff0c;主要功能有&#xff1a;个人每日答题、邀请好友一对一PK答题、排位升级PK答题、专题1V1pk答…

按键LED测试【FPGA】

按钮&#xff1a; 按钮是区分输入输出的&#xff0c; LED配置成输入&#xff0c;是不会亮的。 //timescale 1s/1ns // 【】是预编译&#xff0c;类似C语言的#include // 这是FPGA原语 //晶振时钟 1ns//类型声明 module LED //跟PLC的FB功能块一样&#xff0c;使用前需要实…