2012-04-29 9 views
8

In Bezug auf CRP wenn ich eine leichte Variation davon (unter Verwendung von Template-Template-Parametern) implementieren mag ich einen Compiler-Fehler:Merkwürdiger wiederkehrend template - Variation

template <template <typename T> class Derived> 
class Base 
{ 
public: 
    void CallDerived() 
    { 
     Derived* pT = static_cast<Derived*> (this); 
     pT->Action(); // instantiation invocation error here 
    } 
}; 

template<typename T> 
class Derived: public Base<Derived> 
{ 
public: 
    void Action() 
    { 
    } 
}; 

Ich bin nicht ganz sicher, man würde diese Form gewählt hat (das bedeutet für mich nicht kompilieren) anstelle dieser obwohl die Verwendung (dies funktioniert)

template <typename Derived> 
class Base 
{ 
public: 
    void CallDerived() 
    { 
     Derived* pT = static_cast<Derived*> (this); 
     pT->Action(); 
    } 
}; 

template<typename T> 
class Derived: public Base<Derived<T>> 
{ 
public: 
    void Action() 
    { 
    } 
}; 

Antwort

11

Dies sollte auch kompilieren. Wir müssen nur die anderen Template-Parameter explizit

template <typename T, template <typename T> class Derived> 
class Base 
{ 
public: 
    void CallDerived() 
    { 
     Derived<T>* pT = static_cast<Derived<T>*> (this); 
     pT->Action(); // instantiation invocation error here 
    } 
}; 

template<typename T> 
class Derived: public Base<T,Derived> 
{ 
public: 
    void Action() 
    { 
    } 
}; 
+1

Ziemlich interessant muss man über Typname T in Deklaration zweimal explizit sein ... Nicht wirklich verstehen, warum – Ghita

+1

gerade erkannt, dass abgeleitete muss auch seine T-Parameter übertragen werden. – Ghita

5

im ersten Beispiel wird die Klassenvorlage nimmt tatsächlich Template-Template-Parameter, nicht nur Template-Parameter, wie Sie geschrieben haben:

template <template <typename T> class Derived> 
class Base 
{ 
    //.. 
}; 

Also dieser Code ist nicht sinnvoll:

Derived* pT = static_cast<Derived*> (this); 
pT->Action(); // instantiation invocation error here 

Hier Derived ist ein Template-Template-Argument, das Template-Argument benötigt, die Sie nicht haben zur Verfügung gestellt. In der Tat, in der CallDerived() Funktion, können Sie nicht wissen, Typ Sie müssen, um es zu tun, um zu tun, was Sie vorhaben zu tun.

Der zweite Ansatz ist die richtige Lösung. Benutze es.

+1

angegeben zu bekommen, aber wie stelle ich das Template-Argument in ersten Fall .. abgeleitet Mit * pt nicht funktioniert entweder – Ghita

+1

@Ghita: 'T' nicht in bekannt ist, die Basisklasse. Andere Lösung hat erklärt, wie Sie 'T' an die Basis übergeben können. Aber das ist nicht notwendig, wie Sie für die zweite Lösung gehen sollten. – Nawaz

+1

Manchmal wird T in der Basisklasse benötigt. Z.B. wenn Sie ein Mitglied 'T Action() haben;' Natürlich können Sie eine Traits-Klasse verwenden, die für jede abgeleitete Klasse ein T gibt, aber manchmal möchten Sie, dass T und Derived unabhängig voneinander variieren. In diesem Fall möchten Sie den [ersten] Ansatz mit einer Vorlage + einem Template-Template-Parameter. – TemplateRex