首页 > 代码库 > 6 C++ Boost 函数对象

6 C++ Boost 函数对象



6 C++ Boost 函数对象

目录:
关于bind
bind2nd程序
bind与bind2nd,效果一样
bind1st 减法
bind1st 与bind 做减法
bind2nd调用仿函数
bind 不需要ptr_fun适配
std:bind2nd 与 boost:bind
当参数大于2个,std::bind已经没办法了,boost::bind限10个
bind_api[图]
bind用于函数 以及 函数指针
bind用于函数对象
bind用于函数对象,(用引用避免函数对象的拷贝)
bind 函数成员指针
bind 嵌套
关于mem_fun[图]
boost.function
包装类的成员函数
function与functionN[图]
使用function对象的引用的示例[图]
boost.lambda介绍
lambda出场
lambda相关的文件[图]
lambda的占位符[图]
占位符总是传元素的引用.
lambda操作符表达式01.png
lambda操作符表达式02.png
lambda操作符表达式03.png
lambda操作符表达式04.png
lambda操作符表达式05.png
延迟常量.png
延迟常量实例,






函数对象.png

技术分享





关于bind.png

技术分享



bind2nd程序

pi@raspberrypi:~/boost $ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;

int main()
{
	int a[]={1,2,3,4,5,6};
	transform(a,a+6,a,bind2nd(plus<int>(),10));
	copy(a,a+6,ostream_iterator<int> (cout," "));
	cout << endl;
	return 0;
}
pi@raspberrypi:~/boost $ g++  -Wall main.cpp &&./a.out 
11 12 13 14 15 16 
pi@raspberrypi:~/boost $


bind与bind2nd,效果一样

pi@raspberrypi:~/boost $ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <iterator>
#include <boost/bind.hpp>
using namespace std;

int main()
{
	int a[]={1,2,3,4,5,6};
	transform(a,a+6,a,bind2nd(plus<int>(),10));
	copy(a,a+6,ostream_iterator<int> (cout," "));
	cout << endl;


	transform(a,a+6,a,boost::bind(plus<int>(),_1, 100));//_1占位符
	copy(a,a+6,ostream_iterator<int> (cout," "));
	cout << endl;
	
	return 0;
}
pi@raspberrypi:~/boost $ g++  -Wall main.cpp &&./a.out 
11 12 13 14 15 16 
111 112 113 114 115 116 
pi@raspberrypi:~/boost $


bind1st 减法

pi@raspberrypi:~/boost $ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <iterator>
#include <boost/bind.hpp>
using namespace std;

int main()
{
	int a[]={1,2,3,4,5,6};
	transform(a,a+6,a,bind1st(minus<int>(),50));//bind第1个参数,50去减每一个
	copy(a,a+6,ostream_iterator<int> (cout," "));
	cout << endl;
	return 0;
}
pi@raspberrypi:~/boost $ g++  -Wall main.cpp &&./a.out 
49 48 47 46 45 44 
pi@raspberrypi:~/boost $


bind1st 与bind 做减法

pi@raspberrypi:~/boost $ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <iterator>
#include <boost/bind.hpp>
using namespace std;

int main()
{
	int a[]={1,2,3,4,5,6};
	transform(a,a+6,a,boost::bind(minus<int>(),100,_1));//_1占位符
	copy(a,a+6,ostream_iterator<int> (cout," "));
	cout << endl;
	
	return 0;
}
pi@raspberrypi:~/boost $ g++  -Wall main.cpp &&./a.out 
99 98 97 96 95 94 
pi@raspberrypi:~/boost $


bind2nd调用仿函数

pi@raspberrypi:~/boost $ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <iterator>
#include <boost/bind.hpp>
using namespace std;

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

int main()
{
	int a[]={1,2,3,4,5,6};
	transform(a,a+6,a,bind2nd(ptr_fun(fun),50));//将一个普通的函数适配成一个仿函数
	copy(a,a+6,ostream_iterator<int> (cout," "));
	cout << endl;
	return 0;
}
pi@raspberrypi:~/boost $ g++  -Wall main.cpp &&./a.out 
51 52 53 54 55 56 
pi@raspberrypi:~/boost $


bind 不需要ptr_fun适配


pi@raspberrypi:~/boost $ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <iterator>
#include <boost/bind.hpp>
using namespace std;

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

int main()
{
	int a[]={1,2,3,4,5,6};
	transform(a,a+6,a,bind(fun,_1,50));//bind不需要提前做适配
	copy(a,a+6,ostream_iterator<int> (cout," "));
	cout << endl;
	return 0;
}
pi@raspberrypi:~/boost $ g++  -Wall main.cpp &&./a.out 
51 52 53 54 55 56 
pi@raspberrypi:~/boost $


std:bind2nd 与 boost:bind

pi@raspberrypi:~/boost $ cat main.cpp 
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <boost/bind.hpp>
using namespace std;

struct A
{
	void f(int i) { cout << "A::A()" << i <<endl;}
};

void fun()
{
	vector<A*> v;
	v.push_back(new A);
	v.push_back(new A);
	v.push_back(new A);
	v.push_back(new A);
	int i = 5;
	cout <<"std:bind2nd"<<endl;
	for_each(v.begin(),v.end(),bind2nd(mem_fun(&A::f),i));
	cout <<"boost:bind"<<endl;
	for_each(v.begin(),v.end(),bind(&A::f,_1,i));//boost
}

int main()
{
	fun();
	return 0;
}
pi@raspberrypi:~/boost $ g++  -Wall main.cpp &&./a.out 
std:bind2nd
A::A()5
A::A()5
A::A()5
A::A()5
boost:bind
A::A()5
A::A()5
A::A()5
A::A()5
pi@raspberrypi:~/boost $




当参数大于2个,std::bind已经没办法了,boost::bind限10个

pi@raspberrypi:~/boost $ cat main.cpp 
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <boost/bind.hpp>
using namespace std;

int f3(int a,int b,int c)
{
	return a+b+c;
}

int main()
{
	int a[]={1,2,3,4,5,6};
	transform(a,a+6,a,bind(f3,_1,20,10));
	copy(a,a+6,ostream_iterator<int> (cout," "));
	cout << endl;
	return 0;
}
pi@raspberrypi:~/boost $ g++  -Wall main.cpp &&./a.out 
31 32 33 34 35 36 
pi@raspberrypi:~/boost $



bind_api[图]

技术分享

bind api (0个参数,1个参数)

解读:

bind实际就是一个函数


无参数的bind,需要一个函数对象



bind用于函数 以及 函数指针

chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
using namespace std;
using namespace boost;

int f(int a,int b)
{
	cout << "a="<<a<<" b="<<b<<endl;
	return a+b;
}
int g(int a,int b,int c)
{
	cout << "a="<<a<<" b="<<b<<" c="<<c<<endl;
	return a+b+c;
}

int main()
{
	bind(f,1,8);//返回无元函数对象,返回f(1,8)
	bind(g,1,8,12);//同上

	int x =10;
	bind(f,_1,5)(x);//返回f(x,5);
	bind2nd(ptr_fun(f),6)(x);//返回f(x,6);

	bind(f,5,_1)(x);	//返回f(5,x);
	bind1st(ptr_fun(f),5)(x );//返回f(5,x);

	bind(f,ref(x),_1)(29);//传参数的引用
	bind(f,cref(42),_1)(28);//传const参数的引用
	
	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
a=10 b=5
a=10 b=6
a=5 b=10
a=5 b=10
a=10 b=29
a=42 b=28
chunli@Linux:~/boost$


bind用于函数对象

chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
using namespace std;
using namespace boost;

struct F 
{
	int operator()(int a,int b)
	{
		return a - b;
	}
	bool operator()(long a,long b)
	{
		return a == b;
	}
};

int main()
{
	F f;
	int x = 108;
	//由于函数对象F内部没有定义return_type类型
	//所以下面需要显式的写成bind<int>
	bind<int>(f,_1,_1)(x);

	//由于函数对象less<>内部定义了return_type类型
	//所以下面的bind不需要写成bind<int>
	bind(less<int>(),_1,9)(x);

	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
chunli@Linux:~/boost$



bind用于函数对象,(用引用避免函数对象的拷贝)

chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
using namespace std;
using namespace boost;

struct F 
{
	int s;
	typedef void result_type;
	void operator()(int x)
	{
		s += x;
	}
};

int main()
{
	F f = {0};
	int a[] = {1,2,3};
	for_each(a,a+3,bind(ref(f),_1));//成功
	//for_each(a,a+3,bind(f,_1));	//传函数对象的副本,失败
	cout << f.s << endl;
	assert(f.s == 6);
	
	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
6
chunli@Linux:~/boost$




bind 函数成员指针

chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
using namespace std;
using namespace boost;

struct X 
{
	bool f(int a)
	{
		cout <<"a="<<a<<endl;
		return true;
	}
};

int main()
{
	X x;
	shared_ptr<X> p(new X);
	int i = 5;
	bind(&X::f,ref(x),_1)(i);//x.f(i)
	bind(&X::f,&x,_1)(i);//(&x)->f(i)
	bind(&X::f,x,_1)(i);//(internal copy of x).f(i)
	bind(&X::f,p,_1)(i);//(internal copy of x)->f(i)
	
	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
a=5
a=5
a=5
a=5
chunli@Linux:~/boost$




bind 嵌套

chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/bind/apply.hpp>
#include <boost/ref.hpp>
using namespace std;
using namespace boost;

void f1(int i)
{
	cout << "f1() i="<<i<<endl;
}

void f2(int i)
{
	cout << "f2() i="<<i<<endl;
}

int main()
{
	std::vector< void (*)(int) > v;//函数指针类型
	v.push_back(f1);
	v.push_back(f1);
	v.push_back(f2);
	v.push_back(f2);
	
	for_each(v.begin(),v.end(),bind(apply<void>(),_1,5));
	//for_each(v.begin(),v.end(),bind(_1,5));//失败

	//int k = 99;	
	//for_each(v.begin(),v.end(),bind(apply<void>(),_1,++k));//OK
	

	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
f1() i=5
f1() i=5
f2() i=5
f2() i=5
chunli@Linux:~/boost$



关于mem_fun[图]

技术分享

chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/bind/apply.hpp>
#include <boost/ref.hpp>
using namespace std;
using namespace boost;

struct X
{
	void f()
	{
		cout << "Hello Boost!" << endl;
	}
};

void g(vector<X> &v)//支持直接传对象
{
	for_each(v.begin(),v.end(),boost::mem_fn(&X::f));
}
void h(vector<X*> &v)//支持对象指针
{
	std::for_each(v.begin(),v.end(),boost::mem_fn(&X::f));
}
void k(vector<boost::shared_ptr<X> > const &v)//支持智能指针
{
	std::for_each(v.begin(),v.end(),boost::mem_fn(&X::f));
}

int main()
{
	X x1,x2,x3,x4;
	std::vector<X> v;//函数指针类型
	v.push_back(x1);
	v.push_back(x2);
	v.push_back(x3);
	v.push_back(x4);

	g(v);cout<<"--------------\n";


	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
Hello Boost!
Hello Boost!
Hello Boost!
Hello Boost!
--------------
chunli@Linux:~/boost$


boost.function


chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <vector>

#include <boost/function.hpp>

struct int_div//这是函数对象
{
	float operator()(int x,int y) const
	{
		std::cout << "in struct ";
		return ((float)x)/y;
	}
};

float float_div(float x,float y)//这是函数
{
	std::cout << "float_div ";
	return x/y;
}

void test(boost::function<float(float x,float y)> const& f)
{
	std::cout << f(12,35) <<std::endl;
}

int main()
{
	boost::function<float(int x,int y)> f1;//既可以接收函数对象,又可以接收函数
	f1  =int_div();
	std::cout << f1(23,7) << std::endl;

	boost::function2<float,int,int> f2;//functionN 只能接收N个参数,第一个参数类型为返回值
	f2  =int_div();
	std::cout << f2(22,7) << std::endl;

	test(&float_div);//函数地址
	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
in struct 3.28571
in struct 3.14286
float_div 0.342857
chunli@Linux:~/boost$




包装类的成员函数

chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <vector>
#include <cassert>

#include <boost/function.hpp>
struct X
{
	int foo(int i)
	{
		std::cout << "i="<<i<<std::endl;
		return 1;
	}
};
int main()
{
	//使用boost::function
	boost::function<int(X*,int)> f;
	f =&X::foo;
	X x;
	f(&x,5);

	//使用boost::function N
	boost::function2<int,X*,int> f2;//对象指针占一个
	f2 = &X::foo;
	X x2;
	f(&x2,5);

	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
i=5
i=5
chunli@Linux:~/boost$



function与functionN[图]

技术分享


使用function对象的引用的示例[图]

技术分享



boost.lambda介绍

chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
template <int T>
void add(int& src)
{
	src+=T;
}

void add5(int& src)
{
	src+=5;
}
struct PrintV
{
	void operator()(int v)
	{
		std::cout<< v << " ";
	}
};
int main()
{
	int a[] = {12,3,5,99,434};	
	std::for_each(a,a+5,add<12>);//使用函数指针
	std::for_each(a,a+5,PrintV());//使用函数对象

	std::for_each(a,a+5,add5);
	std::for_each(a,a+5,PrintV());
	std::cout << std::endl;
	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
24 15 17 111 446 29 20 22 116 451 
chunli@Linux:~/boost$




lambda出场

chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <boost/lambda/lambda.hpp>
int main()
{
	using namespace boost::lambda;
	int a[] = {1,2,3,4,5};	

	std::for_each(a,a+5,_1 +=10);//_1 编译器产生函数对象,+=是操作符重载
	std::for_each(a,a+5,std::cout<<_1<<" \n");

	//lambda还支持做手脚
	std::cout << "------\n";
	std::for_each(a,a+5,(++ _1,std::cout<<_1<<" \n"));

	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
11 
12 
13 
14 
15 
------
12 
13 
14 
15 
16 
chunli@Linux:~/boost$



lambda相关的文件[图]

技术分享


lambda的占位符[图]

技术分享


占位符总是传元素的引用.


lambda操作符表达式01.png

lambda操作符表达式02.png

lambda操作符表达式03.png

lambda操作符表达式04.png

lambda操作符表达式05.png

技术分享

技术分享

技术分享

技术分享

技术分享



延迟常量.png

技术分享


延迟常量实例,

chunli@Linux:~/boost$ cat main.cpp 
#include <iostream>
#include <algorithm>
#include <boost/lambda/lambda.hpp>
int main()
{
	using namespace boost::lambda;
	int a[] = {11,12,13,14,15,16};

	//占位符在左边,正常求值
	for_each(a,a+sizeof(a)/sizeof(a[0]),std::cout<<_1<<‘ ‘);
	std::cout<<std::endl;
	
	//++var(_1)将占位符包裹起来
	for_each(a,a+sizeof(a)/sizeof(a[0]),std::cout<< ++var(_1)<<‘ ‘);
	std::cout<<std::endl;

	//立即求值,只进行一次求值,常量不再涉及第二次求值
	for_each(a,a+sizeof(a)/sizeof(a[0]),std::cout<<‘ ‘<<_1);
	std::cout<<std::endl;

	//解决办法,只要在表达式的最前端有一个lambda表达式,其他的都当成lambda表达式
	int index = 0;
	for_each(a,a+sizeof(a)/sizeof(a[0]),std::cout<< --var(index) <<‘ ‘<<_1<<‘ ‘);//只进行一次求值
	std::cout<<std::endl;
	return 0;
}
chunli@Linux:~/boost$ g++ main.cpp -Wall && ./a.out 
11 12 13 14 15 16 
12 13 14 15 16 17 
 121314151617
-1 12 -2 13 -3 14 -4 15 -5 16 -6 17 
chunli@Linux:~/boost$
















本文出自 “魂斗罗” 博客,谢绝转载!

6 C++ Boost 函数对象