C++11函数适配器bind() --- C++11新语法bind() 你了解多少?什么是适配器???

1.介绍

头文件

#include <functional> 

定义

bind函数定义在头文件中,是一个函数模板,它就像一个函数包装器(适配器),接收一个可调用对象(callable object),生成一个新的可调用对象来==“适应”原对象的参数列表==。用它可以把一个原本接收N个参数的函数fn,通过绑定一些参数,返回一个接收M个(M可以大于N,但这么做没什么意义)参数的新函数。同时,使用bind函数还可以实现参数顺序调整等操作。

简而言之

bind函数用于把已知函数与某种参数与进行绑定,形成新的函数。

什么叫做绑定?

更改已知函数调用模式

如何理解bind?

可以将bind函数看作是一个通用的函数适配器,接收一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。调用bind的一般形式:auto newCallable = bind(callable,arg_list);
其中,newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中的参数。
arg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是“占位符”,表示
newCallable的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对
象中参数的位置:_1为newCallable的第一个参数,_2为第二个参数,以此类推。

原型

template <class Fun, class... Args>
bind (Fun&& fun, Args&&... args);

template <class Ret, class Fun, class... Args>
bind (Fun&& fun, Args&&... args);

2.引入

2.1现有语法无法解决

int Myplus(int a, int b)
{
	return a + b;
}

class Sub
{
public:
	int Mysub(int a, int b)
	{
		return a - b;
	}
};

int main()
{
	function<int(int, int)> funcPlus = Myplus;
	function<int(Sub, int, int)> funcSub = &Sub::Mysub;
	map<string, function<int(int, int)>> m =
	{
		{ "+", Myplus},
		{ "-", &Sub::Mysub}
	};
}

即 一个全局函数 一个类 现在我们想要把这两个函数通过包装器包装起来 我们的目的无法达到 因为两个函数传给包装器时 方式不同 包装时无法统一 怎么解决?

class Mycalculator
{
public:
	int Myplus(int a, int b)
	{
		return a + b;
	}
	int Mysub(int a, int b)
	{
		return a - b;
	}
};

int main()
{
	function<int(Mycalculator,int, int)> funcPlus = &Mycalculator::Myplus;
	function<int(Mycalculator, int, int)> funcSub = &Mycalculator::Mysub;
	map<string, function<int(Mycalculator, int, int)>> m =
	{
		{ "+", &Mycalculator::Myplus},
		{ "-", &Mycalculator::Mysub}
	};
}

很明显 上面强制他们统一 同样的也可以把类转成全局函数 但这都不是我们想要的结果 怎么办呢???

此时 bind绑定就出来了…

2.2bind的文档阅读

在这里插入图片描述
返回一个基于fn的函数对象,但其参数绑定为args。
每个实参可以绑定到一个值或一个占位符:
-如果绑定到一个值,调用返回的函数对象将始终使用该值作为参数。
-如果是占位符,调用返回的函数对象会将一个参数传递给调用(其顺序号由占位符指定)。
调用返回的对象返回与fn相同的类型,除非指定了特定的返回类型为Ret(2)(注意,Ret是唯一不能通过传递给此函数的实参隐式推断的模板形参)。
返回对象的类型具有以下属性:
它的函数调用返回与fn相同的参数绑定到args…(或转发,用于占位符)。
对于(1),它可以有一个成员result_type:如果Fn是指向函数或成员函数类型的指针,它被定义为其返回类型的别名。否则,如果存在这样的成员类型,则定义为Fn::result_type。
对于(2),它有一个成员result_type,定义为Ret的别名。
它是可移动构造的,如果它的所有参数的类型都是可复制构造的,那么它也是可复制构造的。两个构造函数都不会抛出,只要没有相应的Fn和Args衰变类型的构造函数…扔。
在这里插入图片描述fn
函数对象,指向函数的指针或指向成员的指针。
Fn应具有可从Fn移动构造的衰变类型。
args……
要绑定的参数列表:值或占位符。
Args中的类型…应具有可从args…中各自的参数移动构造的衰变类型
如果对于任何参数,其衰减类型是reference_wrapper,则将其绑定到其引用的值。

在这里插入图片描述
一个函数对象,被调用时调用fn,其参数绑定到args。

如果fn是指向成员的指针,则返回函数期望的第一个参数是类的对象*fn是成员(或对其的引用,或指向其的指针)。
在这里插入图片描述
在这里插入图片描述

namespace placeholders
{  
    extern /* unspecified */ _1; 
    extern /* unspecified */ _2; 
    extern /* unspecified */ _3;  
    // ...
}

在这里插入图片描述
在这里插入图片描述

2.3bind()绑定函数对于2.1问题的解决

int pLus(int a, int b)
{
	return a + b;
}

class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};

int Mul(int a, int b, int c)
{
	return a * b * c;
}

int Div(int a, int b)
{
	return a / b;
}
using namespace placeholders;
int main()
{
	function<int(int, int)> funcPlus = pLus;

	//function<int(Sub, int, int)> funcSub = &Sub::sub;
	function<int(int, int)> funcSub = bind(&Sub::sub, Sub(), _1, _2);

	function<int(int, int, int)> funcMul = bind(Mul, _1, _2, _3);
	
	map<string, function<int(int, int)>> m =
	{
		{ "+", pLus},
		{ "-", bind(&Sub::sub, Sub(), _1, _2)}
	};

	cout << "funcPlus(1, 2) == " << funcPlus(1, 2) << endl << endl;
	
	cout << "bind(&Sub::sub, Sub(), _1, _2) == " << funcSub(1, 2) << endl << endl;
	cout << "bind(Mul, _1, _2, _3) == " << funcMul(1, 2, 3) << endl << endl;
	auto funcMul2 = bind(Mul, 1, 2, 3);
	cout << "funcMul2() == " << funcMul2() << endl << endl;
	cout << "m["" + ""](1, 2) == " << m["+"](1, 2) << endl << endl;
	cout << "m["" - ""](1, 2) == " << m["-"](1, 2) << endl << endl;

	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿猿收手吧!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值