std__invoke 的使用

std__invoke 的使用

文章目录

  • [std__invoke 的使用](#std__invoke 的使用)
    • [1. `std::invoke` 的功能](#1. std::invoke 的功能)
    • [2. 语法](#2. 语法)
    • [3. 使用场景](#3. 使用场景)
      • [1. 调用普通函数](#1. 调用普通函数)
      • [2. 调用成员函数](#2. 调用成员函数)
      • [3. 调用成员函数(通过指针或引用)](#3. 调用成员函数(通过指针或引用))
      • [4. 调用函数对象(仿函数)](#4. 调用函数对象(仿函数))
      • [5. 调用 Lambda 表达式](#5. 调用 Lambda 表达式)
    • [4. `std::invoke` 的优势](#4. std::invoke 的优势)
    • [5. 注意事项](#5. 注意事项)
    • [6. 示例:综合应用](#6. 示例:综合应用)
    • 总结

std::invoke 是 C++17 引入的一个标准库函数,用于简化函数调用的语法。它允许你通过统一的接口调用普通函数、成员函数、函数对象或者 Lambda 表达式。这使得在处理不同类型的可调用对象时代码更加简洁和一致。

1. std::invoke 的功能

std::invoke 的目的是让你可以通过统一的方式来调用:

  • 普通函数
  • 成员函数
  • 函数对象(仿函数)
  • Lambda 表达式

2. 语法

cpp 复制代码
  template<typename _Callable, typename... _Args>
    invoke(_Callable&& __fn, _Args&&... __args)
    {
      return std::__invoke(std::forward<_Callable>(__fn),
			   std::forward<_Args>(__args)...);
    }
  • callable 是要调用的可调用对象(例如函数指针、成员函数指针、Lambda 表达式等)。
  • args... 是传递给 callable 的参数。

3. 使用场景

1. 调用普通函数

cpp 复制代码
#include <iostream>
#include <functional>

void print_hello(const std::string& name) {
    std::cout << "Hello, " << name << "!" << std::endl;
}

int main() {
    std::invoke(print_hello, "World");
    return 0;
}

在这个例子中,std::invoke 调用了普通函数 print_hello,并传递了一个参数 "World"

2. 调用成员函数

调用成员函数时,需要额外提供对象实例或对象指针。

cpp 复制代码
#include <iostream>
#include <functional>

class MyClass {
public:
void greet(const std::string& name) {
    std::cout << "Hello, " << name << "!" << std::endl;
}
};

int main() {
    MyClass obj;
    std::invoke(&MyClass::greet, obj, "World");
    return 0;
}

在这个例子中,std::invoke 调用了 MyClass 的成员函数 greet,并传递了对象 obj 和参数 "World"

3. 调用成员函数(通过指针或引用)

对于成员函数调用,你可以传递成员函数指针和对象指针(或者引用)。

cpp 复制代码
#include <iostream>
#include <functional>

class MyClass {
public:
void greet(const std::string& name) const {
    std::cout << "Hello, " << name << "!" << std::endl;
}
};

int main() {
    MyClass obj;
    // 使用成员函数指针调用
    std::invoke(&MyClass::greet, obj, "World");
    // 或者可以传递对象指针
    MyClass* ptr = &obj;
    std::invoke(&MyClass::greet, ptr, "World");
    return 0;
}

4. 调用函数对象(仿函数)

std::invoke 同样适用于函数对象(仿函数)。

cpp 复制代码
#include <iostream>
#include <functional>

struct MyFunctionObject {
void operator()(const std::string& name) const {
    std::cout << "Hello, " << name << "!" << std::endl;
}
};

int main() {
    MyFunctionObject obj;
    std::invoke(obj, "World");  // 调用仿函数
    return 0;
}

5. 调用 Lambda 表达式

std::invoke 也可以用于调用 Lambda 表达式。

cpp 复制代码
#include <iostream>
#include <functional>

int main() {
    auto greet = [](const std::string& name) {
        std::cout << "Hello, " << name << "!" << std::endl;
    };

    std::invoke(greet, "World");  // 调用 Lambda 表达式
    return 0;
}

4. std::invoke 的优势

  1. 简化代码:它可以统一调用不同类型的可调用对象(函数、成员函数、Lambda、函数对象等),避免了使用不同的调用方式。
  2. 类型推断:std::invoke 会自动推断参数类型,无需显式指定。
  3. 支持成员函数:它特别适用于调用成员函数,避免了使用 .*->* 等复杂语法。

5. 注意事项

  • std::invoke 是一个通用工具,适用于各种类型的可调用对象。
  • 它的本质是通过反射机制来判断和调用对象。

6. 示例:综合应用

cpp 复制代码
#include <iostream>
#include <functional>

struct MyClass {
void greet(const std::string& name) {
    std::cout << "Hello, " << name << "!" << std::endl;
}

static void static_greet(const std::string& name) {
    std::cout << "Hello from static function, " << name << "!" << std::endl;
}
};

int main() {
    MyClass obj;

    // 调用成员函数
    std::invoke(&MyClass::greet, obj, "Alice");

    // 调用静态成员函数
    std::invoke(&MyClass::static_greet, "Bob");

    // 调用 Lambda
    auto lambda = [](const std::string& name) {
        std::cout << "Hello from lambda, " << name << "!" << std::endl;
    };
    std::invoke(lambda, "Charlie");

    return 0;
}

总结

std::invoke 是一个灵活、强大的工具,它统一了函数、成员函数、函数对象和 Lambda 表达式的调用方式,使得 C++ 中的可调用对象使用变得更加简洁和一致。

相关推荐
cany10006 小时前
C++ -- 可变参数模板
c++
不会C语言的男孩7 小时前
C++ Primer 第2章:变量和基本类型
开发语言·c++
云泽8089 小时前
C++ 可调用对象通关指南:深度解析 Lambda 表达式、function 包装器与 bind 绑定器
开发语言·c++·算法
Tri_Function9 小时前
简单图论大学习
c++
lqqjuly10 小时前
C++ 完整知识体系—从基础语法到现代 C++23 的系统性总结
c++·c++23
王老师青少年编程10 小时前
信奥赛C++提高组csp-s之FHQ Treap
c++·csp·平衡树·信奥赛·csp-s·提高组·fhq treap
QiLinkOS12 小时前
《打破“用爱发电”:一种基于 Gitee 与时间戳的开源权益分配机制探索》
c语言·数据结构·c++·科技·算法·gitee·开源
Irissgwe12 小时前
c++STL--string类
c++·stl·string
Irissgwe12 小时前
c++类型转换
c++·类型转换·explicit·static_cast·const_cast·dynamic_cast·rtti
智者知已应修善业13 小时前
【51单片机用T0定时器方式1,实现0.5S的时间间隔实现第一次一个灯亮、第二次二个灯亮,直到全部灯亮,然后重复整个过程】2023-12-29
c++·经验分享·笔记·算法·51单片机