関数をCの関数に一般的に渡すことができるようにしたいと思います。私はCを数年間使用しており、適切なクロージャと高階関数を実装する際の障壁を認識しています。それはほとんど乗り越えられないです。
StackOverflowを調べて、他の情報源がこの問題について何と言っているかを確認しました。
- 高階関数-in-c
- 無名関数-using-gcc-statement-expressions
- カリー化を行う方法があります
- 関数型プログラミング-c-issue-with-typesのカリー化
- emulating-partial-function-application-in-c
- fake-anonymous-functions-in-c
- マクロ高階関数ジェネレーターを使用した関数型プログラミング
- 最小限の労力で構文糖衣構文としての高階関数
...そして、varargsまたはアセンブリを使用する以外に、銀の弾丸の一般的な答えはありませんでした。アセンブリの骨はありませんが、ホスト言語で機能を効率的に実装できるのであれば、通常はそうしようとしています。
なかなかHOFが持てないので…
高階関数が欲しいのですが、ピンチでデリゲートに落ち着きます。以下のコードのようなもので、Cで実行可能なデリゲート実装を取得できると思います。
このような実装が思い浮かびます。
enum FUN_TYPES {
GENERIC,
VOID_FUN,
INT_FUN,
UINT32_FUN,
FLOAT_FUN,
};
typedef struct delegate {
uint32 fun_type;
union function {
int (*int_fun)(int);
uint32 (*uint_fun)(uint);
float (*float_fun)(float);
/* ... etc. until all basic types/structs in the
program are accounted for. */
} function;
} delegate;
使用例:
void mapint(struct fun f, int arr[20]) {
int i = 0;
if(f.fun_type == INT_FUN) {
for(; i < 20; i++) {
arr[i] = f.function.int_fun(arr[i]);
}
}
}
残念ながら、デリゲートに対するこのアプローチには明らかな欠点がいくつかあります。
- タイプチェックはありません。「fun_type」フィールドをチェックして自分で行うタイプを保存してください。
- タイプチェックにより、コードに追加の条件が導入され、以前よりも乱雑で分岐が多くなります。
- 関数の(安全な)可能な順列の数は、「fun_type」変数のサイズによって制限されます。
- 関数ポインタ定義の列挙型とリストは、マシンで生成する必要があります。些細な場合を除いて、他のものは狂気に接するでしょう。
- 悲しいことに、通常のCを通過することは、たとえばmov-> callシーケンスほど効率的ではありません。これは、おそらくアセンブリで実行できます(多少の困難が伴います)。
Cのデリゲートのようなことをするためのより良い方法を知っている人はいますか?
注:移植性と効率性が高いほど、優れています
また、注: C++用のDonClugstonの非常に高速なデリゲートについて聞いたことがあります。ただし、C++ソリューションには興味がありません。Cだけです。