C++ std::function与std::invoke:可调用对象的统一处理 #
引言 #
在C++中,std::function和std::invoke是两个处理可调用对象的重要工具,它们各自解决了不同的问题。
function与invoke的区别 #
std::function
和 std::invoke
是C++中两个不同的概念,它们在功能和使用场景上存在明显差异。
std::function #
std::function
是一个函数对象的封装器,可以用来封装任意类型的可调用对象,比如函数指针、lambda表达式、函数对象等。通过 std::function
,我们可以将不同类型的可调用对象统一成一种类型,便于存储和传递。
示例代码:
#include <functional>
#include <iostream>
void foo(int a, int b) {
std::cout << "foo(" << a << ", " << b << ")" << std::endl;
}
int main() {
// 将函数指针封装成 std::function 对象
std::function<void(int, int)> f = foo;
f(1, 2);
}
在上述代码中,我们将函数指针 foo
封装成了一个 std::function
对象 f
,然后通过调用 f(1, 2)
来调用函数 foo
。
std::invoke #
std::invoke
是C++17标准引入的一个函数模板,用于调用可调用对象并返回结果。std::invoke
提供了统一的调用语法,无论可调用对象的类型是什么,都可以使用同一种方式进行调用。
示例代码:
#include <functional>
#include <iostream>
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 对象
std::function<void(int, int)> f = foo;
std::invoke(f, a, b);
}
在C++17之前,调用不同类型的可调用对象需要使用不同的语法,比如直接调用函数、使用类对象的运算符重载操作符()来调用函数对象、使用成员函数指针来调用类成员函数等等。而 std::invoke
解决了这种不一致的问题,提供了一种通用的调用方式。
function与invoke的区别 #
- 功能不同:
std::function
用于封装可调用对象,将其转换为一种统一的函数对象类型;而std::invoke
用于调用可调用对象,提供了一种通用的调用语法。 - 使用场景不同:
std::function
适用于需要存储和传递可调用对象的场景;std::invoke
则适用于需要统一调用各种不同类型可调用对象的场景。
总结来说,std::function
和 std::invoke
在C++中的作用和使用场景是不同的,它们各自解决了不同的问题。理解它们的区别有助于在实际开发中正确选择和使用这些工具。