Bagaimana saya dapat menggunakan CRTP di C ++ untuk menghindari overhead fungsi anggota virtual?
Bagaimana saya dapat menggunakan CRTP di C ++ untuk menghindari overhead fungsi anggota virtual?
Jawaban:
Ada dua cara.
Yang pertama adalah dengan menentukan antarmuka secara statis untuk struktur tipe:
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.
};
Yang kedua adalah dengan menghindari penggunaan idiom reference-to-base atau pointer-to-base dan melakukan wiring pada waktu kompilasi. Menggunakan definisi di atas, Anda dapat memiliki fungsi template yang terlihat seperti ini:
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
Jadi, menggabungkan definisi struktur / antarmuka dan pengurangan jenis waktu kompilasi dalam fungsi Anda memungkinkan Anda untuk melakukan pengiriman statis, bukan pengiriman dinamis. Ini adalah inti dari polimorfisme statis.
not_derived_from_base
tidak berasal dari base
, juga bukan berasal dari base
...
Saya sendiri sedang mencari diskusi yang layak tentang CRTP. Teknik Todd Veldhuizen untuk Scientific C ++ adalah sumber yang bagus untuk ini (1.3) dan banyak teknik lanjutan lainnya seperti template ekspresi.
Selain itu, saya menemukan bahwa Anda dapat membaca sebagian besar artikel C ++ Gems asli Coplien di buku Google. Mungkin masih begitu.
dynamic_cast
atau metode virtual.
Saya harus mencari CRTP . Namun, setelah melakukan itu, saya menemukan beberapa hal tentang Polimorfisme Statis . Saya curiga inilah jawaban atas pertanyaan Anda.
Ternyata ATL menggunakan pola ini cukup ekstensif.
Jawaban Wikipedia ini memiliki semua yang Anda butuhkan. Yaitu:
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();
};
Meskipun saya tidak tahu seberapa banyak ini benar-benar membeli Anda. Overhead dari panggilan fungsi virtual adalah (tergantung kompiler, tentu saja):
Sedangkan overhead polimorfisme statis CRTP adalah: