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

相关推荐
沫璃染墨3 小时前
从零入门计算机网络系列(十二):HTTP长连接与会话管理详解——从Connection到Cookie与Session
linux·服务器·c++·tcp/ip·ubuntu·http·交互
xiaoye-duck4 小时前
《C++ 项目:手写大模型接入 SDK》DeepSeek接口设计(下):流式响应实现和测试
开发语言·网络·c++·语言模型
旖旎夜光6 小时前
【C++ 基础入门】类和对象(上):封装、对象模型与 this 指针
开发语言·c++·笔记·学习
小超人诞生日记6 小时前
C++ 智能指针的使用及其原理详解
c++·算法
akinggw7 小时前
libagentcore - 一个基于c++的AI多agent系统升级到2.0版本
开发语言·jvm·c++
繁星蓝雨8 小时前
C++设计原理———多重继承(虚基类、菱形继承、委托、重命名、基类和成员初始化)
c++·委托·多重继承·mi·显式初始化列·虚基类·对象布局
旖旎夜光9 小时前
【C++ 基础入门】命名空间、输入输出、缺省参数与函数重载
开发语言·c++·笔记·学习
扶尔魔ocy10 小时前
【QT入门到晋级】用开源的自定义控件开发
c++·qt·自定义控件
akinggw11 小时前
libsherpacore - 基于 sherpa-onnx 的 C++ 语音交互静态库
c++·交互·语音识别
xiaoye-duck11 小时前
《C++ 项目:手写大模型接入 SDK》ChatGPT接口设计(中):全量响应实现和测试
网络·c++·语言模型·chatgpt