C++17 新特性_第二章 C++17标准库特性_std::invoke和std::invoke_result_t

本文记录C++17新特性之invoke和invoke_result_t.

文章目录

  • [第2章 C++17标准库特性](#第2章 C++17标准库特性)
    • [2.9 std::invoke](#2.9 std::invoke)
      • [2.9.1 invoke作用](#2.9.1 invoke作用)
      • [2.9.2 使用举例](#2.9.2 使用举例)
      • [2.9.3 invoke 和 function对比](#2.9.3 invoke 和 function对比)
    • [2.10 std::invoke_result_t](#2.10 std::invoke_result_t)

第2章 C++17标准库特性

2.9 std::invoke

C++17之前,编写泛型代码处理回调时,调用不同的"可调用对象"(普通函数、函数指针、成员函数指针、以及仿函数(Functors)和 Lambda 表达式)时,需要不同的调用形式:

  • 对于普通函数/Lambda/函数对象,直接调用f(args...)
  • 对于成员函数指针,调用方式,(obj.*f)(args...) 或 (ptr->*f)(args...)
    针对这种不一致的调用,在实现时,需要使用SFINAE模板元代码区别这些情况。

C++17 将这种复杂的逻辑标准化为 std::invoke,让普通开发者也能轻松编写通用的回调逻辑。

2.9.1 invoke作用

invoke包含在 中,核心作用:以统一的语法调用任何可调用对象。

2.9.2 使用举例

示例1:invoke调用不同的可调用对象。

cpp 复制代码
    // 1. 普通函数
    void printNum(int i) {
        std::cout << "Function: " << i << std::endl;
    }

    // 2. 仿函数 (Functor)
    struct Printer {
        void operator()(int i) const {
            std::cout << "Functor: " << i << std::endl;
        }
    };

    // 3. 类成员
    struct Foo {
        int value = 100;
        void print(int i) {
            std::cout << "Member Function: " << i + value << std::endl;
        }
    };

    void test()
    {
        // 调用普通函数
        std::invoke(printNum, 10);
        // Function: 10

        // 调用 Lambda
        std::invoke([](int i) { std::cout << "Lambda: " << i << std::endl; }, 20);
        // Lambda: 20
        
        // 调用仿函数
        Printer p;
        std::invoke(p, 30);
        // Functor: 30
        
        // 调用成员函数 (注意:第一个参数必须是对象实例或指针)
        Foo f;
        std::invoke(&Foo::print, f, 40);  // 传对象
        std::invoke(&Foo::print, &f, 50); // 传指针
       //Member Function : 140
       //     Member Function : 150
    }

示例2:编写一个函数执行器,可执行任何函数。

cpp 复制代码
    // decltype(auto) 返回值
    template<typename Callable,typename ...Args>
    decltype(auto) logAndExecute(Callable&& func, Args &&...args)
    {

        // 使用invoke 统一调用
        if constexpr (std::is_void_v<  std::invoke_result_t<Callable, Args...> >)
        {
			std::invoke(std::forward<Callable>(func), std::forward<Args>(args)...);
			cout << "函数返回void类型,无返回值可打印。" << endl;
        }
        else
        {
			decltype(auto) ret = std::invoke(std::forward<Callable>(func), std::forward<Args>(args)...);
            return ret;
        }
    }

    struct Worker
    {
        void dowork(int id)
        {
            std::cout << "Working on " << id << std::endl;
        }
    };

    void test()
    {
		// 1 调用普通函数
        auto result = logAndExecute([](int x, int y) {
            return x + y;
            }, 10, 20);
        std::cout << "Result: " << result << std::endl;
        // Result: 30
        
        // 2 调用成员函数
        Worker w;
        logAndExecute(&Worker::dowork, &w, 42);
		// Working on 42
    }

2.9.3 invoke 和 function对比

std::function 是一个"容器":用于存储可调用对象,以便在未来某个时刻调用。它涉及类型擦除和运行时开销。

std::invoke 是一个"动作":用于立即执行可调用对象,统一调用语法。它通常用于泛型编程,零运行时开销。

2.10 std::invoke_result_t

见 模板与泛型编程笔记。

https://blog.csdn.net/weixin_43916755/article/details/155234300

相关推荐
zhouwy113几秒前
Linux文件系统与IO编程
linux·c++
王老师青少年编程8 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【哈夫曼贪心】:合并果子
c++·算法·贪心·csp·信奥赛·哈夫曼贪心·合并果子
叼烟扛炮8 小时前
C++第二讲:类和对象(上)
数据结构·c++·算法·类和对象·struct·实例化
样例过了就是过了10 小时前
LeetCode热题100 最长公共子序列
c++·算法·leetcode·动态规划
谭欣辰10 小时前
C++ 排列组合完整指南
开发语言·c++·算法
橙子也要努力变强11 小时前
信号捕捉底层机制-机理篇2
linux·服务器·c++
盐焗鹌鹑蛋11 小时前
【C++】stack和queue类
c++
郝学胜-神的一滴12 小时前
罗德里格斯旋转公式(Rodrigues‘ Rotation Formula)完整推导
c++·unity·godot·图形渲染·three.js·unreal
lzh2004091912 小时前
深入理解进程:从PCB内核结构到写时拷贝的底层实战
linux·c++
aseity13 小时前
跨平台项目中QString 与 非Qt 跨平台动态库在字符集上的一个实用的互操作约定.
c++·经验分享