C ++ 0x:ラムダ式を関数ポインターに変換します

アクティビティの種類ごとに、計算タスクを処理する必要があります。 多くの場合、たとえば、この関数をプロットしたり、方程式を解くために、関数にポインターを渡す必要があります。 さらに、関数ポインターは通常、さまざまなGUIフレームワークで使用され、特定のボタンがクリックされたときに実行されるアクションを示します。

新しいC ++ 0x標準では、スナップが登場しました。 詳細を説明しなくても、クロージャーは他の関数の本体に関数を直接作成できるオブジェクトです。 より詳細な場合-クロージャーを使用すると、機能オブジェクト、つまり演算子()が定義されているオブジェクトを作成できます。 ハブについてはすでにそれらについて書いています:例えばここに

私はイノベーションが本当に好きで、それを使い始めました。 しかし、それは悪いことです。意味では、クロージャーと関数はほとんど同じですが、関数ポインターを使用する必要があるクロージャーは使用できません。 標準によると、キャプチャリストのないクロージャは、関数へのポインタに自由に変換する必要がありますが、実際にはこれは観察されておらず、明らかにまだ実装されていません。 そして、関数ポインターが使用されているクロージャーを使用することは可能ですか?

例を考えてみましょう。 引数が1〜10の値で実行されている間に、関数値のテーブルを印刷できるprintFunctionTable関数が既にあるとします。
void printFunctionTable(int (*func)(int)){
for(int i=1;i<=10;i++) cout << func(i) << " ";
cout << endl;
}

もちろん、関数へのポインターではなく、クロージャーのすぐ下でこの関数を書き換えることができますが、そのような関数は(よくあることですが)閉じたライブラリに配置できます。そのため、相互に変換する方法を探します。

また、値を印刷する必要がある関数を定義します。
int square(int x){
return x*x;
}

次に、関数の二乗表を表示するメイン関数を作成します。
int main(void)
{
printFunctionTable(square);
return 0;
}

コンパイルして実行し、タブレットを入手します。
1 4 9 16 25 36 49 64 81 100

それでは、クロージャを使用して同じこと-数字の立方体-をクランクしてみましょう。
auto cube=[](int x){
return x*x*x;
}

printFunctionTable(cube);

コンパイル時-エラーが発生しました! もちろん、タイプは異なります!
どうすればこれを回避できますか? テンプレートは私たちの助けになります。
template <typename CL>
int closureToFunction(int x){
CL cl;
return cl(x);
}

ここでは、 CLタイプ、つまりクロージャーのタイプによってパラメーター化された関数テンプレートを定義しました。 クロージャーから必要なのは、それを呼び出して値を返すことだけです。

これで、関数へのポインターを使用していた場所でクロージャーを使用できます。 次のようになります。

printFunctionTable(closureToFunction<decltype(cube)>);

コンパイルおよび起動後、タブレットが取得されます。
1 8 27 64 125 216 343 512 729 1000

ウラ!!! -動作します! =)

参考: decltypeはC ++ 0xの新しいキーワードであり、式のタイプ(この場合はクロージャキューブのタイプ)を決定できます。

これですべてです。問題は解決しました。プログラムテキストに沿っていくつかのアクションの関数を簡単に定義できるようになりました。

さらに、署名int(int)のテンプレートのみを作成したことに注意してください。 必要に応じて、他の署名(たとえば、double(int、double)など)を追加できます。 また、便宜上、マクロを作成できます
#define CLOSURE_TO_FUNCTION(cl) closureToFunction<decltype(cl)>

PSインテルC ++コンパイラー11.1コンパイラーでテストされました。理論的には、g ++ 4.5およびVisual Studio 2010で動作するはずです。主なことは、コンパイルを使用するときにフラグを置くことを忘れないことで、c ++ 0xを使用できます。

完全なプログラムコード:
#include <iostream>

using namespace std;

void printFunctionTable(int (*func)(int)){
for(int i=1;i<=10;i++) cout << func(i) << " ";
cout << endl;
}

int square(int x){
return x*x;
}

template int closureToFunction(int x){
CL cl;
return cl(x);
}

#define CLOSURE_TO_FUNCTION(cl) closureToFunction <decltype(cl)>

int main(void)
{
printFunctionTable(square);

auto cube=[](int x){return x*x*x;};
auto quad=[](int x){return x*x*x*x;};

printFunctionTable(CLOSURE_TO_FUNCTION(cube));
printFunctionTable(CLOSURE_TO_FUNCTION(quad));

return 0;
}

Source: https://habr.com/ru/post/J109226/


All Articles