【C++】function包装器

简介: 【C++】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…是一个可变参数包

目录
相关文章
|
2月前
|
存储 编译器 C语言
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题(下)
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题
39 5
|
12天前
|
存储 C++
【C++】string类的使用③(非成员函数重载Non-member function overloads)
这篇文章探讨了C++中`std::string`的`replace`和`swap`函数以及非成员函数重载。`replace`提供了多种方式替换字符串中的部分内容,包括使用字符串、子串、字符、字符数组和填充字符。`swap`函数用于交换两个`string`对象的内容,成员函数版本效率更高。非成员函数重载包括`operator+`实现字符串连接,关系运算符(如`==`, `&lt;`等)用于比较字符串,以及`swap`非成员函数。此外,还介绍了`getline`函数,用于按指定分隔符从输入流中读取字符串。文章强调了非成员函数在特定情况下的作用,并给出了多个示例代码。
|
2月前
|
程序员 编译器 C++
C++中的函数重载(Function Overloading)
C++中的函数重载(Function Overloading)
23 2
|
2月前
|
算法 编译器 C语言
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题(中)
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题
30 2
|
2月前
|
算法 编译器 C语言
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题(上)
从C语言到C++_34(C++11_下)可变参数+ lambda+function+bind+笔试题
19 1
|
1月前
|
算法 编译器 C++
C++多态与虚拟:函数重载(Function Overloading)
重载(Overloading)是C++中的一个特性,允许不同函数实体共享同一名称但通过参数差异来区分。例如,在类`CPoint`中,有两个成员函数`x()`,一个返回`float`,另一个是设置`float`值。通过函数重载,我们可以为不同数据类型(如`int`、`float`、`double`)定义同名函数`Add`,编译器会根据传入参数自动选择正确实现。不过,仅返回类型不同而参数相同的函数不能重载,这在编译时会导致错误。重载适用于成员和全局函数,而模板是另一种处理类型多样性的方式,将在后续讨论中介绍。
|
2月前
|
存储 算法 对象存储
【C++入门到精通】function包装器 | bind() 函数 C++11 [ C++入门 ]
【C++入门到精通】function包装器 | bind() 函数 C++11 [ C++入门 ]
35 1
|
2月前
|
Java 编译器 Linux
【C++11(二)】lambda表达式以及function包装器
【C++11(二)】lambda表达式以及function包装器
|
2月前
|
存储 算法 C++
C++11:lambda表达式 & 包装器
C++11:lambda表达式 & 包装器
20 0
|
4天前
|
设计模式 安全 编译器
【C++11】特殊类设计
【C++11】特殊类设计
24 10