2015-02-09 33 views
7

Ben cRTP kullanarak derleme zamanı polimorfizm uygulamaya çalışırken ve işlevi uygulamak için türetilmiş bir sınıf zorlamak istiyorum ediyorum.CRTP kullanarak statik polimorfizmde saf sanal işlevi taklit mümkün mü?

şu anki uygulama böyledir. fonksiyon sonsuz bir döngü içine düşüyor türetilmiş sınıf f() uygulamak olmasaydı

template <class Derived> 
struct base { 
    void f() { 
     static_cast<Derived*>(this)->f(); 
    } 
}; 

struct derived : base<derived> 
{ 
    void f() { 
    ... 
    } 
}; 

Bu uygulamada, diyoruz.

nasıl saf sanal işlev gibi işlevi uygulamak için türetilmiş bir sınıf zorlarım? Ben static_assert(&base::f != &Derived::f, "...") gibi 'static_assert' kullanmaya çalıştı ama farklı sınıfların üye işlevlerine işaret eden iki üye işlev işaretçileri karşılaştırılabilir olmadığını belirten bir hata mesajı oluşturur.

+0

'ctype :: scan_is' ve' ctype :: do_scan_is' bir göz atın. – Mehrdad

cevap

5

Sen geçersiz kılmak şeyi ve bunun gibi kanca farklı isimler verebilir: fimpl Türetilmiş bir sınıfta geçersiz sürece, yanlışlıkla denilen olamaz böylece tabanında İşte

template <class Derived> 
struct base { 
    void f() { 
     static_cast<Derived*>(this)->fimpl(); 
    } 
    void fimpl() = delete; 
}; 

struct derived : base<derived> { 
    void fimpl() { printf("hello world\n"); } 
}; 

, fimpl = delete.

Ayrıca delete olarak cRTP için "geçici" işareti f içine bir ara saklanma katmanı sopa olabilir:

template <class Derived> 
struct base { 
    void f() { 
     static_cast<Derived*>(this)->f(); 
    } 
}; 

template <class Derived> 
struct intermediate : base<Derived> { 
    void f() = delete; 
}; 

struct derived : intermediate<derived> { 
    void f() { printf("hello world\n"); } 
}; 
+0

Bir orta sınıf koyarak ikinci çözüm harika. – kukyakya

+0

Bunu ilk yoldan yapardım. İkinci sınıf, orta sınıftan miras kalmayı unutursanız F-up'ı riske atar. – tmyklebu

+0

Sanırım bu sadece bir adlandırma sorunudur. Gerçek temeli 'detay' isim alanına koymak ve ara sınıfı 'üs' olarak adlandırmaktan ne haber? – kukyakya

1
template<typename Derived> 
class Base 
{ 
    private: 
    static void verify(void (Derived::*)()) {} 

    public: 
    void f() 
    { 
     verify(&Derived::f); 
     static_cast<Derived*>(this)->f(); 
    } 
}; 

türetilmiş sınıf, kendi başına &Derived::f türünü f uygulamak etmezse derlemeyi kesen void (Base::*)() olur.

C++ 11 beri de variadic şablonla bu fonksiyon jenerik yapabilirsiniz.

template<typename Derived> 
class Base 
{ 
    private: 
    template<typename T, typename...Args> 
    static void verify(T (Derived::*)(Args...)) {} 
}; 
İlgili konular