c++11之functionbind
Posted ych9527
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++11之functionbind相关的知识,希望对你有一定的参考价值。
1.function
1.1function简介
-
类模板std :: function是一个通用的多态函数包装器
-
std :: function的实例可以存储,复制和调用任何可调用的目标 :包括函数,lambda表达式,绑定表达式或其他函数对象,以及指向成员函数和指向数据成员的指针
-
当std::function对象未包裹任何实际的可调用元素,调用该std::function对象将抛出std::bad_function_call异常
-
std::function template <class T> function; // undefined template <class Ret, class... Args> class function<Ret(Args...)>; Ret:被调用函数的返回值 Args...:可变参数列表
-
例子:
- function<int<int,int>>func 表示func可以指向返回值为int,并且有两个int参数的函数
1.2演示
- 包装普通函数、仿函数、成员函数演示
void func1()
{
cout << "普通函数" << endl;
}
struct Test
{
void operator () (int val1,double val2)
{
cout << "仿函数:"<<val1<<" "<<val2<< endl;
}
};
struct Obj
{
static void func2()
{
cout << "静态成员函数" << endl;
}
void func3()
{
cout << "非静态成员函数" << endl;
}
};
int main()
{
function<void()> f1 = func1;
function<void(int,double)> f2 = Test();
function<void()> f3 = Obj::func2;
function<void(Obj)> f4 = &Obj::func3;//非静态成员函数,需要传入一个对象&&显示的取地址
function<void(int a ,int b,int c)> f5 = [](int a,int b,int c){cout << "lambda表达式:"<<a+b+c<< endl; };
f1();
f2(10,12.12);
f3();
f4(Obj());//传入一个匿名对象
f5(10,20,30);
-
operator bool
- 一个类实现operator bool ,就可以让类对象直接去做逻辑真假的判断
1.3作用
- 在某些场景下,可以减少模板实例化的次数,提高模板的效率
//模板函数
template<class F>
void Print(F fun)
{
static int count = 0;//静态的
cout <<"count_val:" <<++count << endl;
cout <<"count_address:" <<&count << endl;
}
void func1()
{
cout << "普通函数" << endl;
}
struct Test
{
void operator () ()
{
cout << "仿函数:"<< endl;
}
};
struct Obj
{
static void func2()
{
cout << "静态成员函数" << endl;
}
void func3()
{
cout << "非静态成员函数" << endl;
}
};
int main()
{
function<void()> f1 = func1;
function<void()> f2 = Test();
function<void()> f3 = Obj::func2;
function<void(Obj)> f4 = &Obj::func3;//非静态成员函数,需要传入一个对象&&显示的取地址
function<void()> f5 = [](){cout << "lambda表达式:"<< endl; };
auto fun4 = [](){cout << "lambda表达式:" << endl; };
cout << "---------直接调用------------" << endl<<endl;
Print(func1);
Print(Test());
Print(Obj::func2);
Print(&Obj::func3);
Print(fun4);
cout << "---------封装后调用------------" << endl;
Print(f1);
Print(f2);
Print(f3);
Print(f4);
Print(f5);
1.4应用
class Solution {
public:
int evalRPN(vector<string>& tokens) {
//第二个函数类型包装一下,作为map的v值类型
//包装的是lambda表达式
//比如K值是+ op[+]返回的是一个lambda表达式,传入对应的数值即可
unordered_map<string,function<int(int,int)>> op=
{
{"+",[](int a,int b) ->int{return a+b;}},
{"-",[](int a,int b) ->int{return a-b;}},
{"*",[](int a,int b) ->int{return a*b;}},
{"/",[](int a,int b) ->int{return a/b;}}
};
stack<int> st;
for(auto&e:tokens)
{
if(e=="+" || e=="-" || e=="*" ||e=="/")
{
int n1=st.top();
st.pop();
int n2=st.top();
st.pop();
st.push(op[e](n2,n1));
}
else
st.push(stoi(e));
}
return st.top();
}
};
2.bind
2.1bind简介
-
template <class Fn, class... Args> bind (Fn&& fn, Args&&... args); template <class Ret, class Fn, class... Args> bind (Fn&& fn, Args&&... args)
- fn:一个可调用对象(可以是函数对象、函数指针、函数引用、成员函数指针、数据成员指针)
- 它的参数将被绑定到args上args:绑定参数列表,参数会被值或占位符替换,其长度必须与f接收的参数个数一致。
-
std::bind函数定义在头文件functional中,是一个函数模板,它就像一个函数适配器,接受一个可调用对象(callable object),生成一个新的可调用对象来**“适应”原对象的参数列表**
-
一般而言,我们用它可以把一个原本接收N个参数的函数func,通过绑定一些参数,返回一个接收M个参数的新函数。同时,使用std::bind函数还可以实现参数顺序调整等操作
-
调用bind的一般形式:auto newfunc=bind(func,arg_list)
- 其中,newfunc本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的func的参数。当我们调用newfunc时,newfunc会调用func,并传给它arg_list中的参数
- _arg_list中的参数可能包含形如_n的名字,其中n是一个整数,这些参数是“占位符”,表示newfunc的参数,它们占据了传递给newCallable的参数的“位置”。数值n表示生成的可调用对象中参数的位置:_1为newCallable的第一个参数,_2为第二个参数,以此类推
2.2绑定的价值
#include "test.h"
int Add(int x, int y)
{
return x + y;
}
struct Sub
{
int sub(int x, int y)
{
return x - y;
}
};
int main()
{
//bind的返回值类型就是function
function<int(int, int)> func1 = bind(Add, placeholders::_1, placeholders::_2);
auto func2 = bind(Add, placeholders::_1, placeholders::_2);
cout <<"function<int(int, int)> func1"<<" "<<func1(10, 20) << endl;
cout <<"auto func2" <<" "<<func2(10, 20) << endl<<endl;
//正常function用法每次需要传入对象
function<int(Sub, int, int)> func3 = &Sub::sub;
cout <<"正常function用法"<<func3(Sub(),11, 22) << endl;
//绑定后可以不传入对象
function<int(int, int)> func4 =bind(&Sub::sub,Sub(),placeholders::_1,placeholders::_2);
cout <<"绑定后不传对象:" <<func4(11, 22) << endl;
//绑定后,可以更换参数位置
function<int(int, int)> func5 = bind(&Sub::sub, Sub(), placeholders::_2, placeholders::_1);
cout << "绑定后,可以更换参数位置:" << func5(11, 22) << endl;
- 调用类的成员函数的时候,绑定后,可以不传入对象
- 可以更换参数的位置
以上是关于c++11之functionbind的主要内容,如果未能解决你的问题,请参考以下文章