2012-04-29 12 views
8

En cuanto CRP si quiero aplicar una ligera variación de la misma (con el parámetro de plantilla plantilla) me sale un error de compilación:Curiosamente recurrente plantilla - variación

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

No estoy exactamente seguro de que uno elegiría este formulario (que no se compila para mí) en lugar de utilizar esto, sin embargo (esto funciona)

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

Respuesta

11

Esto debería compilar también. Sólo tenemos que conseguir que el otro parámetro de plantilla especifica explícitamente

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

Bastante interesante tiene que ser explícito sobre typename T en declaración dos veces ... No entiendo por qué – Ghita

+1

Acaba de darse cuenta de que derivada también tiene que transmitir su parámetro T. – Ghita

5

En el primer ejemplo, la plantilla de clase realmente tiene plantilla de parámetro de plantilla, no sólo parámetro de plantilla, como usted ha escrito:

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

lo que este código no tiene sentido:

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

Aquí Derived es un argumento de plantilla de la plantilla que necesita parámetro de plantilla que usted no lo hizo proporcionado a ella. De hecho, en la función CallDerived(), no puede conocer el tipo que debe proporcionarle, para hacer lo que pretende hacer.

El segundo enfoque es la solución correcta. Úselo.

+1

Pero ¿Cómo proporciono el argumento de plantilla en primer caso .. El uso de derivados * pt no funciona bien – Ghita

+1

@Ghita: 't' no se conoce en la clase base. Otra solución ha explicado cómo puede pasar 'T' a la base. Pero eso no es necesario, ya que debes buscar la segunda solución. – Nawaz

+1

A veces se necesita T en la clase base. P.ej. al tener un miembro 'T Action();' Por supuesto, podría usar una clase de rasgos que proporcione una T para cada clase derivada, pero a veces desea que T y Derived varíen de forma independiente. En ese caso, quiere el [primer] enfoque con una plantilla + un parámetro plantilla-plantilla. – TemplateRex

Cuestiones relacionadas