2012-02-02 27 views
10

Me gustaría utilizar una clase de plantilla para proporcionar algunas funcionalidades comunes a algunas clases secundarias que son muy similares. La única variación es la enumeración que cada uno usa.Usar una enumeración como parámetro de plantilla

Esta es la clase padre

template<typename T> class E_EnumerationBase : public SimpleElement 
{ 
public: 
    E_EnumerationBase(); 
    virtual bool setValue(QString choice); 
    virtual T getState(); 

protected: 
    T state; 
    QHash<QString, T> dictionary; 
}; 

template<typename T> E_EnumerationBase<T>::E_EnumerationBase() { 
    state = 0; 
} 

template<typename T> bool E_EnumerationBase<T>::setValue(QString choice) { 
    T temp; 
    temp = dictionary.value(choice, 0); 
    if (temp == 0) { 
     return false; 
    } 

    value = choice; 
    state = temp; 
    return true; 
} 

template<typename T> T E_EnumerationBase<T>::getState() { 
    return state; 
} 

Este es uno de los niños

enum TableEventEnum { 
    NO_VALUE = 0, 
    ATTRACT = 1, 
    OPEN = 2, 
    CLOSED = 3 
}; 

class E_TableEvent : public E_EnumerationBase<enum TableEventEnum> 
{ 
public: 
    E_TableEvent(); 
}; 

Este es el constructor

E_TableEvent::E_TableEvent() 
{ 
    state = NO_VALUE; 
    dictionary.insert("attract", ATTRACT); 
    dictionary.insert("open", OPEN); 
    dictionary.insert("closed", CLOSED); 
} 

El enlazador está lanzando este error:

e_tableevent.cpp:6: error: undefined reference to `E_EnumerationBase<TableEventEnum>::E_EnumerationBase()' 

¿Se puede usar una enumeración como parámetro para una plantilla como esta?

+4

"* El compilador arroja este error: *" No, el _linker_ está arrojando ese error. – ildjarn

+0

¿Su definición de constructor está en el archivo de encabezado? – Lol4t0

+0

No, la definición está en un archivo fuente separado. El error aparece en el enlace. – IslandCow

Respuesta

18

Las enumeraciones pueden ser parámetros de la plantilla exactamente de la misma forma que los ints.

enum Enum { ALPHA, BETA }; 

template <Enum E> class Foo { 
    // ... 
}; 

template <> void Foo <ALPHA> :: foo() { 
    // specialise 
} 

class Bar : public Foo <BETA> { 
    // OK 
} 

Pero simplemente no han proporcionado una definición para E_EnumerationBase::E_EnumerationBase()

Esto no es un problema con las plantillas o sucesiones. Es lo mismo que si esta escrito:

struct Foo { 
    Foo(); 
} 
int main() { 
    Foo foo; 
} 
+0

Mi mal. Implementación incluida de constructor y métodos. – IslandCow

+0

¿Puede enviarlo a [ideone.com] (http://www.ideone.com) o similar de tal forma que ese sea el único error? Sería útil ver los números de línea, etc. Por ahora, no creo que 'public E_EnumerationBase ' se compile en absoluto. – spraff

+0

Es _is_ compila. _Y enlaces_: http://ideone.com/Blaw9 – Lol4t0

7

La sintaxis va para argumentos de valor como lo es para TypeName argumentos. Básicamente, que acaba de sustituir typename con el nombre de su enum:

enum Foo { Bar, Frob }; 

template <Foo F> struct Boom {}; // primary template 
template <> struct Boom<Bar> {}; // specialization of whole class 

... 

template <> void Boom<Frob>::somefun() {} // specialization of single member 

No escribir código de la plantilla graves si no se entiende en serio plantillas.


Sin embargo, mi verdadera recomendación sería la de obtener una buena lectura de las plantillas en primer lugar. Si se puede gastar el dinero, recomiendo plantillas Josuttis/de Vandevoorde C++: La guía completa

+1

¿Estás sugiriendo que la enumeración se usa por su valor y no como tipo? Principalmente, estoy tratando de restringir los valores en la tabla hash. – IslandCow

0

No se puede mover definición de función de plantilla de archivo de origen independiente.

No se compilará en absoluto, porque las plantillas no se pueden compilar, solo las instancias de plantilla pueden.

Su código en un archivo separado no se compila, por eso no tiene ninguna definición para E_EnumerationBase<TableEventEnum>::E_EnumerationBase(). Es por eso que obtienes el error del enlazador.

Simplemente mueva todo el código de la plantilla a su encabezado.

+0

* No [la enumeración] no se compilará en absoluto "* - Enums don no se compila * per se *. No ocupan espacio en la clase. Esto está en contraste con, por ejemplo, un int estático que requiere una definición y causa una asignación. – jww

0

Solo para referencia, ya que parece que usa Qt: solo eche un vistazo a Q_ENUM, QMetaEnum y QMetaEnum::fromType. Estos pueden ser útiles para inicializar su diccionario.

Cuestiones relacionadas