【现代C++】functional模板库之function详解

本文详细介绍了C++标准库中的std::function模板,包括如何包装普通函数、函数指针、类成员函数指针(包括静态和对象成员)、函数对象以及lambda表达式。通过实例演示,展示其灵活的调用和封装能力。
摘要由CSDN通过智能技术生成


1. 参考文档

两个常用的C++参考文档:


2. std::funtion 简介

std::function 是一个类模板,其声明如下:

// MS C++ 2013
template<class _Fty> class function;
template<class _Fty> class function : public _Get_function_impl<_Fty>::type { ... }

// GCC 4.8.2
template<typename _Signature>                  class function;
template<typename _Res, typename... _ArgTypes> class function<_Res(_ArgTypes...)>
    : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>, private _Function_base { ... }

// cplusplus.com
template <class T> function;     // undefined
template <class Ret, class... Args> class function<Ret(Args...)>;

关于此类模板的说明:

  • std::function 是一个函数包装器模板 function wrapper template ,原本来自于 boost 库,对应其中的 boost::function 函数包装器,C++11将其纳入了标准库之中。
  • std::function 能包装任何类型的可调用元素 callable element ,例如普通函数 function函数对象 function object 。包装器对象的类型仅仅依赖于其调用特征 call signature ,而不依赖于可调用元素自身的类型 callable element type itself
  • 一个 std::function 类型的实例对象可以包装这样几种可调用类型 callable object普通函数 function普通函数指针 function pointer类成员函数指针 pointer to member 或者任意类型的函数对象 function object(例如定义了 operator() 并且拥有函数闭包)。
  • std::function 对象可以被拷贝 copied移动 moved ,并且可以使用指定的调用特征直接调用可调用类型
  • std::function 对象没有包装任何实际的可调用元素时,即为空函数 empty function ,调用该对象将抛出 std::bad_function_call 异常

模板参数的说明:

  • T:通用类型,但实际通用类型模板 generic template 并没有被定义,只有当 T 的类型为形如 Ret(Args...) 的函数类型才能工作。
  • Ret:调用函数返回值的类型。
  • Args:函数参数类型。这是一个能包装任意数量类型的模板参数。对于指向成员函数的指针,第一个类型应为指向成员的类类型的引用 a reference to the class type the member pointed is a member

3. std::function 样例

① 包装普通函数

非模板类型

#include <iostream>
#include <functional>

int sub(int i, int j) { return i - j; } 

int main() {
	std::function<int(int, int)> f = sub;
	std::cout << f(1, 2) << std::endl; //-1
	return 0;
} 

模板类型

#include <iostream>
#include <functional>

template <typename T> 
T sub(T i, T j) { return i - j; } 

int main() {
	std::function<double(double, double)> f = sub<double>; //传递模板参数
	std::cout << f(1, 2) << std::endl;	
	return 0;
} 

② 包装普通函数指针

非模板类型

#include <iostream>
#include <functional>

int sub(int i, int j) { return i - j; } 

int main() {
	std::function<int(int, int)> f = &sub;
	std::cout << f(1, 2) << std::endl;	
	return 0;
} 

模板类型

#include <iostream>
#include <functional>

template <typename T> 
T sub(T i, T j) { return i - j; } 

int main() {
	std::function<double(double, double)> f = &sub<double>; //传递模板参数
	std::cout << f(1, 2) << std::endl;	
	return 0;
}  

③ 包装类成员函数指针

a. 类静态成员函数

非模板类型

#include <iostream>
#include <functional>

class Ops {
public:
	static int sub(int i, int j) { return i - j; } 
};

int main() {
	std::function<int(int, int)> f = &Ops::sub;
	std::cout << f(1, 2) << std::endl;	
	return 0;
} 

模板类型

#include <iostream>
#include <functional>

class Ops {
public:
	template <typename T>
	static T sub(T i, T j) { return i - j; } 
};

int main() {
	std::function<double(double, double)> f = &Ops::sub<double>;
	std::cout << f(1, 2) << std::endl;	
	return 0;
} 

b. 类对象成员函数

非模板类型

#include <iostream>
#include <functional>

class Ops {
public:
	int sub(int i, int j) { return i - j; } 
};

int main() {
	Ops m;
	std::function<int(int, int)> f = std::bind(&Ops::sub, 
		&m, std::placeholders::_1, std::placeholders::_2); //return m.sub
	std::cout << f(1, 2) << std::endl;	
	return 0;
} 

模板类型

#include <iostream>
#include <functional>

class Ops {
public:
	template <typename T>
	T sub(T i, T j) { return i - j; } 
};

int main() {
	Ops m;
	std::function<double(double, double)> f = std::bind(&Ops::sub<double>, 
		&m, std::placeholders::_1, std::placeholders::_2); //return m.sub<double> 
	std::cout << f(1, 2) << std::endl;	
	return 0;
} 

④ 包装函数对象

非模板类型

#include <iostream>
#include <functional>

struct Ops {
	int operator()(int i, int j) {
		return i - j;
	}
};

int main() {
	std::function<int(int, int)> f = Ops();
	std::cout << f(1, 2) << std::endl;	
	return 0;
} 

模板类型

#include <iostream>
#include <functional>

template <typename T> 
struct Ops {
	T operator()(T i, T j) {
		return i - j;
	}
};

int main() {
	std::function<double(double, double)> f = Ops<double>();
	std::cout << f(1, 2) << std::endl;	
	return 0;
} 

⑤ 包装lambda表达式对象

#include <iostream>
#include <functional>

auto sub = [](int i, int j) { return i - j; };

int main() {
	std::function<int(int, int)> f = sub;
	std::cout << f(1, 2) << std::endl;	
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

memcpy0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值