function包装器
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...是一个可变参数包