C ++でCRTPを使用して仮想メンバー関数のオーバーヘッドを回避するにはどうすればよいですか?
C ++でCRTPを使用して仮想メンバー関数のオーバーヘッドを回避するにはどうすればよいですか?
回答:
2つの方法があります。
1つ目は、型の構造に対して静的にインターフェイスを指定する方法です。
template <class Derived>
struct base {
void foo() {
static_cast<Derived *>(this)->foo();
};
};
struct my_type : base<my_type> {
void foo(); // required to compile.
};
struct your_type : base<your_type> {
void foo(); // required to compile.
};
2番目の方法は、base-to-baseまたはpointer-to-baseイディオムの使用を避け、コンパイル時に配線を行うことです。上記の定義を使用して、次のようなテンプレート関数を作成できます。
template <class T> // T is deduced at compile-time
void bar(base<T> & obj) {
obj.foo(); // will do static dispatch
}
struct not_derived_from_base { }; // notice, not derived from base
// ...
my_type my_instance;
your_type your_instance;
not_derived_from_base invalid_instance;
bar(my_instance); // will call my_instance.foo()
bar(your_instance); // will call your_instance.foo()
bar(invalid_instance); // compile error, cannot deduce correct overload
したがって、関数内で構造/インターフェース定義とコンパイル時の型の演繹を組み合わせると、動的ディスパッチの代わりに静的ディスパッチを行うことができます。これが静的ポリモーフィズムの本質です。
not_derived_from_base
から派生していないbase
、またそれが由来しているbase
...
私自身、CRTPについてのきちんとした議論を探していました。Todd Veldhuizen's Techniques for Scientific C ++は、これ(1.3)や、式テンプレートのような他の多くの高度なテクニックに最適なリソースです。
また、GoogleブックでCoplienのオリジナルのC ++ Gems記事のほとんどを読むことができることもわかりました。多分それはまだ事実です。
dynamic_cast
仮想メソッドが必要になるときはいつでも。
このウィキペディアの回答には、必要なものがすべて含まれています。すなわち:
template <class Derived> struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
これが実際にどれだけあなたを買うかはわかりませんが。仮想関数呼び出しのオーバーヘッドは(もちろんコンパイラに依存します):
CRTP静的ポリモーフィズムのオーバーヘッドは次のとおりです。