2012-04-29 12 views
8

Per quanto riguarda CRP se voglio implementare una leggera variazione di esso (con il parametro template) ottengo un errore di compilazione:template Curiosamente ricorrente - variazione

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() 
    { 
    } 
}; 

io non sono esattamente sicuro uno avrebbe scelto questo modulo (che non compila per me) invece di utilizzare questo, però (questo funziona)

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() 
    { 
    } 
}; 

risposta

11

Anche questo dovrebbe essere compilato. Abbiamo solo bisogno di ottenere l'altro parametro modello specificato esplicitamente

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

Abbastanza interessante deve essere esplicito riguardo il typname T nella dichiarazione due volte ... Non capisco veramente perché – Ghita

+1

Appena realizzato che derivato deve trasmettere anche il suo parametro T. – Ghita

5

Nel primo esempio, il modello di classe prende effettivamente template parametro di template, non solo modello parametro, come hai scritto:

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

Quindi, questo codice non ha senso:

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

Ecco Derived è un argomento template che ha bisogno di template argomento che non avete fatto fornito ad esso. Infatti, nella funzione CallDerived(), non è possibile conoscere il tipo che è necessario fornire, al fine di fare ciò che si intende fare.

Il secondo approccio è la soluzione corretta. Usalo.

+1

Ma come faccio a fornire l'argomento modello nel primo caso .. Utilizzando derivato * pt non funziona neanche – Ghita

+1

@Ghita: 'T' non è noto in la classe base. Un'altra soluzione ha spiegato come puoi passare 'T' alla base. Ma questo non è necessario, come dovresti fare per la seconda soluzione. – Nawaz

+1

Talvolta T è necessario nella classe Base. Per esempio. quando si ha un membro 'T Action();' Sicuramente, si potrebbe usare una classe di tratti che fornisce una T per ogni classe derivata, ma a volte si desidera che T e Derived varino in modo indipendente. In tal caso, vuoi il [primo] approccio con un template + un parametro template template. – TemplateRex

Problemi correlati