function包装器的使用
function
包装器的使用格式
function<返回类型(参数)>
#include<iostream> #include<functional> using namespace std; class test { public: static void func1(int a,int b) { cout << a + b << endl; } void func2(int a, int b) { cout << a + b << endl; } }; int Add(int a, int b) { return a + b; } class test1 { public: int operator()(int a, int b) { return a + b; } }; int main(void) { function<void(int, int)>f1 = &test::func1; f1(2, 3); function<void(test,int, int)>f2 = &test::func2; f2(test(),5, 7); function<int(int, int)>f3 = Add; cout << f3(9, 10) << endl; function<int(int,int)>f4=[](int a, int b)->int {return a + b; }; cout << f4(10, 12) << endl; function<int(int, int)>f5 = test1(); cout << f5(13, 14)<<endl; return 0; }
给你一个字符串数组tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'
、'-'
、'*'
和'/'
。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
示例 1:
输入:tokens = ["2","1","+","3","*"] 输出:9 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
输入:tokens = ["4","13","5","/","+"] 输出:6 解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:
输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"] 输出:22 解释:该算式转化为常见的中缀算术表达式为: ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 = ((10 * (6 / (12 * -11))) + 17) + 5 = ((10 * (6 / -132)) + 17) + 5 = ((10 * 0) + 17) + 5 = (0 + 17) + 5 = 17 + 5 = 22
提示:
1 <= tokens.length <= 104
tokens[i]
是一个算符("+"
、"-"
、"*"
或"/"
),或是在范围[-200, 200]
内的一个整数
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
- 平常使用的算式则是一种中缀表达式,如
( 1 + 2 ) * ( 3 + 4 )
。 - 该算式的逆波兰表达式写法为
( ( 1 2 + ) ( 3 4 + ) * )
。
逆波兰表达式主要有以下两个优点:
- 去掉括号后表达式无歧义,上式即便写成
1 2 + 3 4 + *
也可以依据次序计算出正确结果。 - 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
如果用常规方法会有很多
switch case
:
class Solution { public: int evalRPN(vector<string>& tokens) { stack<long long>st; for(auto& str: tokens) { if(str=="+"||str=="-" ||str=="*"||str=="/") { long long right=st.top(); st.pop(); long long left=st.top(); st.pop(); switch(str[0]) { case'+': st.push(left+right); break; case'-': st.push(left-right); break; case'*': st.push(left*right); break; case'/': st.push(left/right); break; } }else { st.push(stoll(str)); } } return st.top(); } };
但如果引入function
代码就会简单很多了
class Solution { public: int evalRPN(vector<string>& tokens) { map<string,function<long long(long long,long long )>>opFunc { {"+",[](long long a,long long b)->long long{return a+b;}}, {"-",[](long long a,long long b)->long long{return a-b;}}, {"*",[](long long a,long long b)->long long{return a*b;}}, {"/",[](long long a,long long b)->long long{return a/b;}}, }; stack<long long>res; for(auto &str:tokens) { if(opFunc.find(str)!=opFunc.end()) { int right=res.top(); res.pop(); int left=res.top(); res.pop(); res.push(opFunc[str](left,right)); }else { res.push(stoll(str)); } } return res.top(); } };
用function
去接收一个Lambda
表达式。
function的实现原理
//R为返回值类型,A是传入的参数类型 template<typename R, typename... A> class myfunction<R(A...)> { public: using PFUNC = R(*)(A...); myfunction(PFUNC pfunc) :_pfunc(pfunc) {} R operator()(A... arg) { return _pfunc(arg...); // hello(arg) } private: PFUNC _pfunc; };
PFUNC = R(*)(A...)
是一个函数指针类型的别名。
_pfunc
是一个函数指针。构造函数直接拷贝函数指针的地址就能拿到函数的地址了。
A…是一个可变参数包