[C++] 関数ラッパー

関数ラッパーの使用

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... は可変パラメータ パッケージです

おすすめ

転載: blog.csdn.net/AkieMo/article/details/132163802