天天看点

1.5 std::function和bind绑定器

1.5 std::function和bind绑定器

本文为图书《深入应用C++11:代码优化与工程级应用 祁宇编著》1.5章内容笔记

1.5.1 可调用函数

可调用对象

  1. 函数指针
  2. 具有operator()成员函数的类对象(仿函数)
  3. 可被转化为函数指针的类对象
  4. 类成员(函数)指针

代码:

#include <iostream>
#include <map>
using namespace std;

//1.5.1
	/*可调用对象
	(1)函数指针
	(2)具有operator()成员函数的类对象(仿函数)
	(3)可被转化为函数指针的类对象
	(4)类成员(函数)指针
	*/
void func(void)
{
	cout << "func" << endl;
}

struct Foo
{
	void operator()(void)
	{
		cout << "Foo" << endl;
	}
};

struct Bar
{
	using fr_t = void(*)(void);
	static void func(void)
	{
		cout << "Bar" << endl;
	}

	operator fr_t(void)
	{
		return func;
	}
};

struct A
{
	int a;

	void mem_func(void)
	{
		cout << "A:" <<a<< endl;
	}
};

int main()
{   
	void (*func_ptr)(void) = &func;//1.函数指针
	func_ptr();

	Foo foo;//仿函数
	foo();

	Bar bar;//3.可被转换为函数指针的类对象
	bar();


	void(A::* mem_func_ptr)(void) = &A::mem_func;//4.类成员函数指针

	int A::* mem_obj_ptr = &A::a;//或者是类成员指针

	A aa;
	aa.*mem_obj_ptr = 3;
	(aa.*mem_func_ptr)();
	

	return 0;
}
           

1.5.2 std::function

std::function是可调用对象的包装器。它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象。通过指定它的模板参数,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延时执行它们。

#include <iostream>
#include <functional>//std::function
using namespace std;

//1.5.1
	/*可调用对象
	(1)函数指针
	(2)具有operator()成员函数的类对象(仿函数)
	(3)可被转化为函数指针的类对象
	(4)类成员(函数)指针
	*/
//__FUNCTION__ 返回函数名
void func(void)
{
	cout << __FUNCTION__ << endl;
}

class Foo
{
public:
	static int foo_func(int a)
	{
		cout << __FUNCTION__ << "("<<a<<")"<<endl;
		return a;
	}
};

class Bar
{
public:
	int operator()(int a)
	{
		cout << __FUNCTION__ << "(" << a << ")" << endl;
		return a;
	}
};

int main()
{   
	//格式:std::function<返回类型(参数类型)>函数名

	std::function<void(void)>fr1 = func;//绑定一个普通函数
	fr1();
	//绑定一个类的静态成员函数
	std::function<int(int)>fr2 = Foo::foo_func;
	fr2(123);
	
	Bar bar;
	fr2 = bar;
	fr2(321);

	return 0;
}
           

std::function作为回调函数

#include <iostream>
#include <functional>//std::function
using namespace std;

class A
{
	std::function<void()>callback_;
public:
	A(const std::function<void()>& f) :callback_(f) {}

	void notify(void)
	{
		callback_();
	}
};

class Foo
{
public:
	void operator()()
	{
		cout << __FUNCTION__ << endl;
	}
};

int main()
{   
	Foo foo;
	A aa(foo);
	aa.notify();

	return 0;
}
           

std::function 作为函数入参

#include <iostream>
#include <functional>//std::function
using namespace std;

void call_when_even(int x, const::function<void(int)>& f)
{
	if (!(x & 1))//x%2==0
	{
		f(x);
	}
}

void optput(int x)
{
	std::cout << x << " ";
}

int main()
{   
	for (int i = 0; i < 10; ++i)
	{
		call_when_even(i, optput);
	}
	std::cout << std::endl;
	return 0;
}
           

1.5.3 std::bind绑定器

std::bind用来将可调用对象与其参数一起进行绑定

  1. 将可调用对象与其参数一起邦定成一个仿函数;
  2. 将多元(参数个数为n,n>1)可调用对象转成一元或者(n-1)元可调用对象,即只绑定部分参数;
#include <iostream>
#include <functional>//std::function
using namespace std;

void call_when_even(int x, const::function<void(int)>& f)
{
	if (!(x & 1))//x%2==0
	{
		f(x);
	}
}

void optput(int x)
{
	std::cout << x << " ";
}

void optput_add_2(int x)
{
	std::cout << x + 2 << " ";
}


int main()
{   
	
	{
		auto fr = std::bind(optput, std::placeholders::_1);//std::placeholders占位符,c++11中有29个占位符,分别是_1~_29,代表传入第几个参数
		//使用auto承接返回值,如此可不关心返回值类型
        for (int i = 0; i < 10; ++i)
		{
			call_when_even(i, fr);
		}
		std::cout << std::endl;
	}
	
	{
		auto fr2 = std::bind(optput_add_2, std::placeholders::_1);
		for (int i = 0; i < 10; ++i)
		{
			call_when_even(i, fr2);
		}
		std::cout << std::endl;
	}
	return 0;
}
           

使用std::placeholders来决定空位参数将会属于调用发生时的第几个参数

#include <iostream>
#include <functional>//std::function
using namespace std;

void output(int x,int y)
{
	std::cout << x << " "<<y<<endl;
}

int main()
{   
	std::bind(output, 1, 2)();//1 2
	std::bind(output, std::placeholders::_1, 2)(1);//1 2
	std::bind(output, 2, std::placeholders::_1)(1);//2 1

	//std::bind(output, 2, std::placeholders::_2)(1);//error 调用时没有第二个参数
	std::bind(output, 2, std::placeholders::_2)(1,2);//2 2 调用时的第一个参数被吞掉了

	std::bind(output, std::placeholders::_1, std::placeholders::_1)(1,2);//1 1
	std::bind(output, std::placeholders::_2, std::placeholders::_2)(1, 2);//2 2

	std::bind(output, std::placeholders::_1, std::placeholders::_2)(1, 2);//1 2
	std::bind(output, std::placeholders::_2, std::placeholders::_1)(1, 2);//2 1

	return 0;
}
           

std::bind和std::function配合使用,将类的成员函数的指针和其对象进行绑定,转换为一个仿函数放入std::function对象中存储

#include <iostream>
#include <functional>//std::function
using namespace std;

class A
{
public:
	int i_;

	void output(int x, int y)
	{
		std::cout << x << " " << y << endl;
	}
};


int main()
{   
	A a;
	std::function<void(int, int)>fr = std::bind(&A::output,&a, std::placeholders::_1, std::placeholders::_2);
	/*
	// FUNCTION TEMPLATE bind (implicit return type)
	template <class _Fx, class... _Types>
	_NODISCARD _Binder<_Unforced, _Fx, _Types...> bind(_Fx&& _Func, _Types&&... _Args) {
		return _Binder<_Unforced, _Fx, _Types...>(_STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...);
	}

	// FUNCTION TEMPLATE bind (explicit return type)
	template <class _Ret, class _Fx, class... _Types>
	_NODISCARD _Binder<_Ret, _Fx, _Types...> bind(_Fx&& _Func, _Types&&... _Args) {
		return _Binder<_Ret, _Fx, _Types...>(_STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...);
}
	*/
	fr(1, 2);//指向类成员函数的指针

	std::function<int&(void)>fr_i = std::bind(&A::i_, &a);
	fr_i() = 123;

	std::cout << a.i_ << std::endl;
	
	return 0;
}
           

std::bind 组合使用

#include <iostream>
#include <vector>
#include <functional>//std::function
#include <algorithm>
using namespace std;

int main()
{   
	std::vector<int>vec = { 2,1,3,5,4,6,10,8,7,9 };
	int count = std::count_if(vec.begin(), vec.end(), std::bind(std::less<int>(),std::placeholders::_1, 5));//<5
	cout<< count <<endl;//count = 4
	count = std::count_if(vec.begin(), vec.end(), std::bind(std::less<int>(), 5, std::placeholders::_1));//>5
	cout << count << endl;//count = 5
	//找出vec_2数组中大于5小于9的个数
	std::vector<int>vec_2 = { 2,1,3,5,4,6,10,8,7,9,11,12 };
	using std::placeholders::_1;
	auto f_1 = std::bind(std::greater<int>(), _1, 5);//判断是否大于5
	auto f_2 = std::bind(std::less<int>(), _1, 9);//判断是否小于9
	auto f = std::bind(std::logical_and<bool>(), f_1, f_2);//是否同时满足上述条件
	count = std::count_if(vec_2.begin(), vec_2.end(), f);
	cout << count << endl;

	return 0;
}
           

继续阅读