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

posted @ 2023-08-24 22:30  Hayaizo  阅读(2)  评论(0编辑  收藏  举报