C++11 std::function

可调用对象

可调用对象,是可以被调用的实体。

通俗来说:x(...)

满足以下条件之一即可

  • 普通函数 / 静态成员函数
  • 函数指针Ret(*)(Args...)
  • 成员函数指针Ret (C::*)(Args...),调用方式特殊)
  • lambda 表达式对象(本质是编译器生成的类对象)
  • 函数对象 / 仿函数(functor) :定义了 operator() 的类/对象
  • std::function:类型擦除后的可调用包装器
  • std::bind 结果(C++11 起,可调用)

std::function

头文件:#include <functional>
std::function 本质上是一个类型擦除的包装器,统一存放和管理各种类型的可调用对象。

函数签名

cpp 复制代码
template< class >  
class function; /* undefined */

template< class R, class... Args >  
class function<R(Args...)>;

要求里面的 callable 能以 Args... 调用,并且返回值能转成 R

基本用法

cpp 复制代码
// 普通函数 || 函数指针
int add(int a, int b) {return a + b;}

function<int(int, int)> f = add;
int x = f(1, 2);

// lambda 
function<int(int)> f = [](int x){ return ++x; };
int x = f(5);

// 仿函数
struct Mul {
  int operator()(int a, int b) const { return a * b; }
};

function<int(int,int)> h = Mul{};
int z = h(2, 3); // 6

进阶用法

类型擦除带来的统一接口。

这里使用 function 可以放入相同函数类型的不同类型

回调列表
cpp 复制代码
int add(int a, int b) {return a + b;}

struct Mul {
  int operator()(int a, int b) const { return a * b; }
};

vector<function<int(int,int)>> v;
v.push_back(add);
v.push_back(Mul{});

for (auto e : v) {
	e(10, 3);
}
回调参数
cpp 复制代码
void run(std::function<int(int)> op) {
  int r = op(10);
}

run([](int x){ 
	return x * x; 
});

注意事项

空状态

std::function 可以是"空的":

如果对空的 std::function 直接调用,会抛:

  • std::bad_function_call
cpp 复制代码
std::function<void()> f; 
if (!f) { /* 空 */ }

try { 
	f(); 
} catch (const std::bad_function_call&) {
	// ...
}

std::function 绑定安全

相关推荐
myloveasuka4 小时前
Java与C++多态访问成员变量/方法 对比
java·开发语言·c++
2301_821700534 小时前
C++编译期多态实现
开发语言·c++·算法
奥地利落榜美术生灬4 小时前
c++ 锁相关(mutex 等)
开发语言·c++
xixihaha13244 小时前
C++与FPGA协同设计
开发语言·c++·算法
重庆小透明4 小时前
【java基础篇】详解BigDecimal
java·开发语言
ID_180079054734 小时前
模拟1688商品详情的Python API实现,返回符合风格的JSON数据
开发语言·python·json
小小怪7505 小时前
C++中的函数式编程
开发语言·c++·算法
金山几座5 小时前
C#学习记录-事件
开发语言·学习·c#
小杍随笔5 小时前
【Rust 语言编程知识与应用:基础数据类型详解】
开发语言·后端·rust
Yupureki5 小时前
《MySQL数据库基础》1. 数据库基础
c语言·开发语言·数据库·c++·mysql·oracle·github