Sanal üye işlevlerinin ek yükünden kaçınmak için CRTP'yi C ++ 'da nasıl kullanabilirim?
Sanal üye işlevlerinin ek yükünden kaçınmak için CRTP'yi C ++ 'da nasıl kullanabilirim?
Yanıtlar:
İki yol var.
İlki, türlerin yapısı için arayüzü statik olarak belirtmektir:
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.
};
İkincisi, referanstan-tabana veya işaretçi-tabana deyiminin kullanımından kaçınmak ve kablolamayı derleme zamanında yapmaktır. Yukarıdaki tanımı kullanarak, aşağıdakilere benzeyen şablon işlevlerine sahip olabilirsiniz:
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
Dolayısıyla, işlevlerinizde yapı / arabirim tanımını ve derleme zamanı türü çıkarımını birleştirmek, dinamik gönderim yerine statik dağıtım yapmanızı sağlar. Statik polimorfizmin özü budur.
template<class T> bar(base2<T> &obj) { obj.quux(); }
- yani farklı bir bar()
uygulamaya sahip ikinci bir temel sınıf - ekleyin ve CRTP'nin faydası ortaya çıkar.
Ben de CRTP ile ilgili düzgün tartışmalar arıyordum. Todd Veldhuizen'in Techniques for Scientific C ++ , bu (1.3) ve ifade şablonları gibi diğer birçok gelişmiş teknik için harika bir kaynaktır.
Ayrıca, Coplien'in orijinal C ++ Gems makalesinin çoğunu Google Books'ta okuyabileceğinizi öğrendim. Belki hala durum budur.
dynamic_cast
veya sanal yöntemlerle.
CRTP'ye bakmam gerekiyordu . Ancak bunu yaptıktan sonra Statik Polimorfizm hakkında bazı şeyler buldum . Sorunuzun cevabının bu olduğundan şüpheleniyorum.
ATL'nin bu kalıbı oldukça yoğun bir şekilde kullandığı ortaya çıktı .
Bu Wikipedia cevabı ihtiyacınız olan her şeye sahiptir. Yani:
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();
};
Bunun seni ne kadar satın aldığını bilmeme rağmen. Bir sanal işlev çağrısının ek yükü (derleyiciye bağlıdır, elbette):
CRTP statik polimorfizminin ek yükü:
not_derived_from_base
türetilmiş değildirbase
, ne de türemiş olduğunubase
...