2012-02-02 38 views
10

Vorrei utilizzare una classe template per fornire alcune funzionalità comuni ad alcune classi figlio molto simili. L'unica variazione è l'enumerazione che ciascuno usa.Utilizzo di un'enumerazione come parametro del modello

Questa è la classe 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; 
} 

Si tratta di uno dei bambini

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

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

Questo è il costruttore

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

Il linker sta gettando questo errore:

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

È possibile utilizzare un'enumerazione come parametro per un modello come questo?

+4

"* Il compilatore lancia questo errore: *" No, il _linker_ lancia questo errore. – ildjarn

+0

La definizione del costruttore è nel file di intestazione? – Lol4t0

+0

No, la definizione è in un file sorgente separato. L'errore si presenta sul link. – IslandCow

risposta

18

Le enumerazioni possono essere parametri del modello esattamente nello stesso modo in cui gli inte possono.

enum Enum { ALPHA, BETA }; 

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

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

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

Ma semplicemente non hai fornito una definizione per E_EnumerationBase::E_EnumerationBase()

Questo non è un problema con i modelli o ereditarietà. È lo stesso come se si scrivesse questo:

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

Il mio male. Implementazione inclusa di costruttore e metodi. – IslandCow

+0

Potete per favore postarlo su [ideone.com] (http://www.ideone.com) o simili in una forma tale che sia l'unico errore? Sarebbe utile vedere i numeri di linea ecc. Per ora non credo che 'public E_EnumerationBase ' compili affatto. – spraff

+0

It_is_ compiles. _And links_: http://ideone.com/Blaw9 – Lol4t0

7

La sintassi va per argomenti di valore come per gli argomenti typename. In pratica, è sufficiente sostituire typename con il nome del 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 

Non scrivere sul serio codice modello a meno che non si capisce sul serio modelli.


Tuttavia, la mia vera raccomandazione sarebbe quella di ottenere una buona lettura su modelli prima. Se si riesce a spendere i soldi, vi consiglio Modelli Josuttis/di Vandevoorde C++: La guida completa

+1

stai suggerendo che l'enum viene usato per il suo valore e non come tipo? In primo luogo, sto cercando di limitare i valori nella tabella hash. – IslandCow

0

Non è possibile spostare definizione di funzione di modello per il file di origine separato.

Là non sarebbe stato compilato affatto, perché i modelli non possono essere compilati, solo le istanze modello possono.

Il tuo codice in un file separato non viene compilato, ecco perché non hai alcuna definizione per E_EnumerationBase<TableEventEnum>::E_EnumerationBase(). Ecco perché ottieni l'errore linker.

Basta spostare tutto il codice del modello nell'intestazione.

+0

* Lì [l'enum] non verrebbe compilato affatto * * - Enums don essere compilato * di per sé *. Non occupano spazio nella classe. Ciò è in contrasto con, ad esempio, un int statico che richiede una definizione e causa un'allocazione. – jww

0

Solo per riferimento, come sembra utilizzare Qt: basta dare un'occhiata a Q_ENUM, QMetaEnum e QMetaEnum::fromType. Questi possono tornare utili per inizializzare il tuo dizionario.

Problemi correlati