ここから(endo)ファンクタは、オブジェクトを取得して同じタイプの別のオブジェクトで変換できるものです。ファンクタの最も単純な例は、IDです。endofunctorのコンセプトまたはインターフェイス
struct Identity {
template <typename T>
T Apply(T x) {
return x
}
};
一般的なFunctorを識別する「Functorタイプ」が必要です。私は何をしたいのようなコードを記述している:
class Sum {
public:
Sum(Functor* f, Functor* g) :
f_(f),
g_(g) {}
template <typename T>
T Apply(T x) { return f_->Apply(x) + g_->Apply(x); }
private
Functor* f_;
Functor* g_;
};
私の心に来た最初のアイデアは、仮想クラスを使用して、もちろんです:
struct Functor {
template <typename T>
virtual T Apply(T x) = 0;
};
このアプローチの解決不可能な問題は、テンプレートということですバーチャルにすることはできません。
次に、私はC++の概念を使ってみました。しかし、Specifying a concept for a type that has a member function template using Concepts Liteと C++ Concepts: Can I define a concept that is itself a template?に記載されているように、「テンプレート化された概念」を持つことはできません。
最後に、私はHow to achieve "virtual template function" in C++につまずいてきたので、私は、次の可能な実装を思い付いた:
struct Functor {
template <typename T>
T Apply(const T& x); // No more virtual!!!
};
// ... Identity and Sum declarations properly inheriting from Functor ...
template <typename T>
T Functor::Apply(T x) {
if (Identity* specialized =
dynamic_cast<Identity*>(this)) {
return specialized->Apply(x);
} else if (const Sum* specialized =
dynamic_cast<const Sum*>(this)) {
return specialized->Apply(x);
} else ...
}
これがコンパイルされていても、それが最善の解決策ではありません。主な問題は、パフォーマンスとコードの繰り返しです。 パフォーマンスの問題は、FunctorでApplyが呼び出されるたびに、Functor :: Apply内の長いif節が解決されなければならないという事実に由来します。これは大きな問題です.Functorを深く入れ子にすることができます(Applyを呼び出すとFunctor :: Applyに複数の呼び出しが行われる可能性があります)。新しいFunctorを定義するたびに、Functor :: Modifyを変更して新しいif節を追加する必要があるため、「コードの繰り返し」の問題は非常に自明です。
私がここで求めているのは、Sumのようなクラスを作成できるFunctorインターフェイス/コンセプトを定義する適切な(クリーンな)方法があるかどうかです。 C++の概念と重いテンプレートのメタプログラミングが受け入れられます。
p.s.すべてのコードスニペットは、目的に応じてできるだけシンプルに保たれています。構造体の代わりにクラスを使用することや、const識別子を追加することや一意のポインタを使用することを避けることは避けてください。
私はstd :: functionをファンクタとして使用しようとします。 –
"C++ 1z"には概念がありません。 –
タイプ「T」がすべての関数で同じ場合は、仮想関数を使用する場合は、関数レベルではなくクラスレベルで移動することができます。ただし、最適な解決策ではない可能性があります。すでに提案したように、私は 'std :: function'が役立つかどうかを調べることから始めます。 – Phil1970