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

相关推荐
无限进步_1 小时前
深入理解顺序表:从原理到完整实现
c语言·开发语言·数据结构·c++·算法·链表·visual studio
繁华似锦respect2 小时前
C++ 无锁队列(Lock-Free Queue)详细介绍
linux·开发语言·c++·windows·visual studio
liu****2 小时前
九.操作符详解
c语言·开发语言·数据结构·c++·算法
666HZ6662 小时前
C语言——交换
c语言·c++·算法
Mr_WangAndy2 小时前
C++14 新特性_第二章 C++14 标准库特性_std::exchange,std::quoted
c++·exchange·c++40周年·quoted·c++14新特性
无限进步_2 小时前
基于顺序表的通讯录系统设计与实现
c语言·开发语言·数据结构·c++·后端·算法·visual studio
宠..2 小时前
使用纯代码设计界面
开发语言·c++·qt
小此方2 小时前
Re:从零开始的链式二叉树:建树、遍历、计数、查找、判全、销毁全链路实现与底层剖析
c语言·数据结构·c++·算法
筱砚.2 小时前
【C++——文件操作案例】
开发语言·c++