C++11 - 関数ラッパー
序文:
Vue框架:
プロジェクトからVue の
OJ算法系列:
魔法のトリックを学ぶ - アルゴリズムの詳細な説明
Linux操作系统:
Fenghou Qimen - linux
関数ラッパー:
呼び出しオブジェクト:
- 呼び出しオブジェクトの分類:
int ret = func(x);
//func可能是什么呢?
- 関数名
- 関数ポインタ
- ファンクターオブジェクト
- ラムダ式オブジェクト
テンプレートの効率:
- 呼び出しオブジェクトが多すぎるため、テンプレートの使用が非効率的になります。
template<class F, class T>
T useF(F f, T t){
static int count = 0; //一定为static
cout<<"count : "<<count++<<endl;
cout<<"&count : "<<&count<<endl;
return f(x);
}
//f的三种类型:
double func1(double x){
return i/2;
}
struct Functor{
double operator()(double x){
return x/3;
}
};
auto func2 = [](double x){
return x/4;
};
int main(){
useF(func1, 10);
useF(Functor(), 10);
useF(func2, 10);
return 0;
}
- 実行結果: 3 つの異なるカウント アドレス
- 原因分析:
- クラス F は 3 つの異なる具象タイプに対応します
- 3 つの useF() 関数をインスタンス化する
- 各 useF() 関数には独自の静的変数が含まれます
ラッパー:
効果:
- 異なる呼び出し可能オブジェクトを同じ型にラップすることも、
テンプレート認識時に同じカテゴリとみなされます。 - これは呼び出し元オブジェクトの型、
特に使いにくかった auto の型が増加したことに相当し、
パラメーターと戻り値に応じて型を function<()> として記録することもできるようになりました。
使用法:
- ヘッド ファイル:
#include <functional>
- 声明:
//对函数/函数指针:
function<double(double)> f1 = func1;
//对仿函数类:
function<double(double)> f2 = Functor();
//对lambda表达式:
function<double(double)> f3 = func2;
ラッパークラスの内部関数:
ラッパークラスの静的関数:
- 非組み込み関数のラップとほぼ同じ
class Calculator{
public:
int sum(int x, int y){
return x+y;
}
};
int main(){
function<int(int, int)> f4 = &Calculator::sum; //可不加&
return 0;
}
ラッパークラスの非静的関数:
- 通常の関数のラップとは 2 つの違いがあります。
- プラスアンパサンド
- 静的関数が属するクラスをラッパークラスで宣言します。
- 呼び出し時にインスタンス オブジェクトを渡す必要があります。
class Calculator{
public:
static int sub(int x, int y){
return x+y;
}
};
int main(){
function<int(Calculator, int, int)> f4 = &Calculator::sub;
f4(Calculator(), 1, 2);
return 0;
}
証明:
- ラッパーの後のすべての関数が同じクラスに属することを証明します。
#include <iostream>
#include <cstring>
#include <functional>
using namespace std;
template<class F, class T>
T useF(F f, T t){
static int count = 0; //一定为static
cout<<"count : "<<count++<<endl;
cout<<"&count : "<<&count<<endl;
return f(t);
}
double func1(double x){
return x/2;
}
struct Functor{
double operator()(double x){
return x/3;
}
};
auto func2 = [](double x){
return x/4;
};
class Test{
public:
static double sfunc(double x){
return x/5;
}
double dfunc(double x){
return x/6;
}
};
int main(){
function<double(double)> f1 = func1;
function<double(double)> f2 = Functor();
function<double(double)> f3 = func2;
useF(f1, 10);
useF(f2, 10);
useF(f3, 10);
function<double(double)> f4 = Test::sfunc;
function<double(Test, double)> f5 = &Test::dfunc;
useF(f4, 10);
cout<<"f5:"<<f5(Test(), 10);
/*
useF(f5, 10);
f5和f1~f4传参不同,所以 暂时 不能放入useF()函数中
学完绑定后即可
*/
return 0;
}
- 操作結果:
バインドバインディング:
効果:
パラメータを渡す順序を調整します。
- placeholders::_n: 現在位置の値が関数の n 番目のパラメーターに渡されることを示します
void func(int x, int y){
cout<<"x:"<<x <<" "<<"y:"<<y<<endl;
}
function<int(int ,int)> f1 = bind(func, placeholders::_1, placeholders::_2);
f1(1, 2);
function<int(int ,int)> f2 = bind(func, placeholders::_2, placeholders::_1);
f2(1, 2);
- 実行結果:
1 2
2 1
パラメータの数を調整します。
- クラス内の非静的関数の場合は、クラスをバインドしてオブジェクトを提供します。
class Test{
public:
static double sfunc(double x){
return x/5;
}
double dfunc(double x){
return x/6;
}
};
function<double(Test, double)> f5 = &Test::dfunc;
f5(Test(), 10);
function<double(Test, double)> f6 = bind(&Test::dfunc, Test());
f6(10);
- クラス内の非静的関数 + クラス オブジェクトを 1 ステップで function() にバインドします。