関数ラッパーの使用
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
記法で算術式を表す文字列の配列が与えられます。
この式を評価してください。式の値を表す整数を返します。
知らせ:
- 有効な演算子は
'+'
、、、'-'
および'*'
です'/'
。 - 各オペランド (オペランド) には、整数または別の式を指定できます。
- 2 つの整数間の除算は、常に0 に向かって切り捨てられます。
- 式にはゼロによる除算演算はありません。
- 入力は、逆ポーランド表記で表現された算術式です。
- 答えとすべての中間計算結果は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 + ) * )
。
逆ポーランド語表現には、次の 2 つの主な利点があります。
- 括弧を外せば式は明確になり、上記の式を書いても
1 2 + 3 4 + *
順序に基づいて正しい結果を計算することができます。 - スタック操作に適しています。数値が検出されると、その数値がスタックにプッシュされ、演算子が検出されると、スタックの上部にある 2 つの数値が計算のために取り出され、その結果がスタックにプッシュされます。
従来の方法を使用すると、次のような問題が数多く発生します
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
。
機能実装原理
//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... は可変パラメータ パッケージです