企业网站建设调研报告,网页网站设计公司排行榜,排名查询系统,网上购物平台哪个好文章目录 包装器1、functional2、绑定 这一篇比较简短#xff0c;只是因为后要写异常和智能指针#xff0c;所以就把它单独放在了一篇博客#xff0c;后面新开几篇博客来写异常和智能指针 包装器
1、functional
包装器是一个类模板#xff0c;对可调用对象类型进行再封装… 文章目录 包装器1、functional2、绑定 这一篇比较简短只是因为后要写异常和智能指针所以就把它单独放在了一篇博客后面新开几篇博客来写异常和智能指针 包装器
1、functional
包装器是一个类模板对可调用对象类型进行再封装适配可调用对象比如函数指针lambda等。包装器的头文件是functional。
template class T function;
template class Ret, class... Args
class functionRet(Args...)
模板参数说明:
Ret:被调用函数的返回类型
Args...:被调用函数的形参实际使用
int f(int a, int b)
{cout f endl;return a b;
}struct Functor
{
public:int operator() (int a, int b){cout Functor endl;return a b;}
};int main()
{//int(*pf1)(int, int) f;函数指针functionint(int, int) f1 f;functionint(int, int) f2 Functor();functionint(int, int) f3 [](int a, int b) {cout lambda endl;return a b; };cout f1(1, 2) endl;cout f2(10, 20) endl;cout f3(100, 200) endl;return 0;
}三个int第一个是函数返回值类型后两个是参数类型。包装起包装起来的就可以传给模板参数 mapstring, functionint(int, int) opFuncMap;opFuncMap[函数指针] f1;opFuncMap[仿函数] Functor();opFuncMap[lambda] [](int a, int b) {cout lambda endl;return a b;};cout opFuncMap[lambda](1, 2) endl;看一个题
逆波兰表达式求值
给你一个字符串数组 tokens 表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意
有效的算符为 ‘’、‘-’、‘*’ 和 ‘/’ 。 每个操作数运算对象都可以是一个整数或者另一个表达式。 两个整数之间的除法总是 向零截断 。 表达式中不含除零运算。 输入是一个根据逆波兰表示法表示的算术表达式。 答案及所有中间计算结果可以用32位整数表示。 之前的写法
class Solution {
public:int evalRPN(vectorstring tokens) {stackint st;for(auto str : tokens){if(str || str - || str / || str *){int right st.top();st.pop();int left st.top();st.pop();switch(str[0]){case :st.push(leftright);break;case -:st.push(left-right);break;case *:st.push(left*right);break;case /:st.push(left/right);break;}}else{st.push(stoi(str));}}return st.top();}
};用包装器后
class Solution {
public:int evalRPN(vectorstring tokens) {stackint st;mapstring, functionint(int, int) opFuncMap {{, [](int a, int b){return a b; }},{-, [](int a, int b){return a - b; }},{*, [](int a, int b){return a * b; }},{/, [](int a, int b){return a / b; }}};//这里就是map的初始化用C11的列表初始化for(auto str : tokens){if(opFuncMap.count(str)){int right st.top();st.pop();int left st.top();st.pop();st.push(opFuncMap[str](left, right));}else{st.push(stoi(str));}}return st.top();}
};包装器也可以包装成员函数。
class Plus
{
public:static int plus1(int a, int b){return a b;}double plus2(double a, double b){return (a b) * _rate;}
private:int _rate 2;
};int main()
{
class Plus
{
public:Plus(int rate 2):_rate(rate){}static int plus1(int a, int b){return a b;}double plus2(double a, double b){return (a b) * _rate;}
private:int _rate 2;
};int main()
{functionint(int, int) f1 Plus::plus1;functionint(Plus, double, double) f2 Plus::plus2;cout f1(1, 2) endl;cout f2(Plus(), 20, 20) endl;Plus p1(3);cout f2(p1, 20, 20) endl;return 0;
}静态成员函数可以直接调用而非静态的需要在第一个位置加上类名因为有this指针然后后面的Plus前加上静态函数也可以加上这个使用这个函数的时候非静态需要在第一个参数位置放上类的对象可以是匿名对象如果在声明f2时传的是*Plus那么下面调用时就必须传对象的地址所以就不能传匿名对象的地址因为右值无法取地址。
包装器本质上是仿函数f1f2f3就是对象然后调用operator()传过去参数然后operator()再去调用对应函数传类的对象就用对象来调用传指针就指针来调用。
2、绑定
绑定是一个函数模板用来调整参数。绑定是一个通用的函数适配器接受一个可调用对象可调用对象就是三个函数指针、lambda、仿函数生成一个新的可调用对象来适配。
bind函数第一个参数是一个万能引用左右值都可传然后后面的是占位符_1表示第一个参数_2表示第二个参数以此类推这些占位符是一个placeholders空间里。
int Print(int a, int b)
{cout a ;cout b endl;
}int main()
{Print(10, 20);auto RP bind(Print, placeholders::_2, placeholders::_1);RP(10, 20);//再次调用就换了顺序了。return 0;
}如果bind写着_1在_2前面那就没换顺序要换顺序占位符就得对应着写。bind函数会返回一个对象我们可以用auto来推演类型还可以用functionvoid(int, int)。实际调用的还是Print不过适配器就是套了一个壳。
绑定真正有用的是改变参数个数
用这段代码做例子
class Sub
{
public:Sub(int rate):_rate(rate){}int func(int a, int b){return (a - b) * _rate;}
private:int _rate;
};class Solution {
public:int evalRPN(vectorstring tokens) {stackint st;mapstring, functionint(int, int) opFuncMap {{, [](int a, int b) {return a b; }},{-, [](int a, int b) {return a - b; }},{*, [](int a, int b) {return a * b; }},{/, [](int a, int b) {return a / b; }}};//这里就是map的初始化用C11的列表初始化for (auto str : tokens){if (opFuncMap.count(str)){int right st.top();st.pop();int left st.top();st.pop();st.push(opFuncMap[str](left, right));}else{st.push(stoi(str));}}return st.top();}
};int main()
{functionint(Sub, int, int) fSub Sub::func;fSub(Sub(1), 10, 20);return 0;
}这是上面包装器的写法。这样的写法无法给opFuncMap传fSub对象因为参数个数不一致这时候就是绑定的作用体现了。 functionint(int, int) fSub bind(Sub::func, Sub(1), placeholders::_1, placeholders::_2);fSub(10, 20);把Sub(1)对象显式地传给func函数顺序没有变只是第一个参数显示传剩下两个就从_1开始排顺序。也可以对其他参数来绑定。 functionint(int, int) fSub bind(Sub::func, placeholders::_1, 10, placeholders::_2);fSub(Sub(1), 20);本篇gitee
结束。