Bagaimana saya dapat menggunakan CRTP di C ++ untuk menghindari overhead fungsi anggota virtual?
89
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 daribase
, juga bukan berasal daribase
...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.
sumber
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.
sumber
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:
sumber