2012-08-05 8 views
6

Esto es lo que quiero lograr. El componente de hoja heredará Component<ParentT>, otros heredarán Component<ParentT, ChildT>redeclaración de parámetros de la plantilla

template <typename T> 
class Component{ 
    protected: 
    typedef Component<T> ParentComponentT; 
    ... 
}; 

template <typename ParentT, typename ChildT> 
class Component: public Component<ParentT>{ 
    protected: 
    typedef std::vector<ChildT*> CollectionT; 
    ... 
}; 

Pero el problema es conseguir volver a declarar los parámetros de plantilla. y no puedo mover el segundo primero porque el segundo hereda el primero.

error: redeclared with 2 template parameter(s)
note: previous declaration ‘template class Component’ used 1 template parameter(s)

+1

Ignorando plantillas variadic por el momento, las plantillas tienen un número fijo de parámetros; un solo 'Component <>' no puede tener uno y dos parámetros. Esto se parece mucho a un [problema XY] (http://meta.stackexchange.com/q/66377/166663): ¿qué intentas lograr en realidad? – ildjarn

+0

Entonces, ¿cuál es la buena manera de modelarlo? 'Componente '? –

+0

Eso depende: ¿por qué quieres que la base y el niño tengan el mismo nombre? Dales diferentes nombres de tipo y no tendrás problemas. – ildjarn

Respuesta

3

Esto compila y por lo que yo entiendo que hace lo que le gusta:

#include <vector> 

class NoneT {}; 

template <typename ParentT,typename ChildT=NoneT> 
class Component: public Component<ParentT>{ 
    protected: 
    typedef std::vector<ChildT*> CollectionT; 
}; 

de especialización para NoneT:

template<> 
template<typename T> 
class Component<T,NoneT>{ 
protected: 
    typedef Component<T> ParentComponentT; 
}; 

int main(){ 
    typedef Component<double> someT; 
    typedef Component<double,int> someT2; 
    typedef Component<double,void> someT3; 
} 

someT tendrá ParentComponentT y someT2 tendrá CollectionT.

EDIT:

respuesta al comentario/pregunta a continuación: typename ChildT=noneT significa que el valor por defecto será ChildTnoneT. Por lo tanto, si no se proporciona un segundo argumento de plantilla, se usará el tipo noneT.

La especialización define el contenido de la clase para esa versión de un solo argumento.

Edit2:

Como sé de la charla que utilice componentes como una clase base, que sugieren que en lugar de algo así como

class myclass: public Component<Section, Line> 

podría usar herencia múltiple

class myclass: public ParentComponent<Section>, CollectionComponent<Line> 

con

template <typename T> 
class ParentComponent{ 
    protected: 
    typedef Component<T> ParentComponentT; 
}; 

template <typename ChildT> 
class CollectionComponent { 
    protected: 
    typedef std::vector<ChildT*> CollectionT; 
}; 
+0

¿por qué 'ChildT = NoteT' o' ChildT = void' si primera plantilla? Lo estás especializando en el segundo en –

+0

Aclaré que ahora –

+0

si no se da un segundo argumento de plantilla irá a la segunda versión de la plantilla. ¿Por qué debería buscar el parámetro predeterminado? –

Cuestiones relacionadas