web-dev-qa-db-fra.com

Utilisation d'une énumération comme paramètre de modèle

J'aimerais utiliser une classe de modèle pour fournir des fonctionnalités communes à certaines classes enfants très similaires. La seule variation est l'énumération que chacun utilise. 

C'est la classe parente 

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;
}

C'est l'un des enfants

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

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

C'est le constructeur

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

L'éditeur de liens renvoie cette erreur:

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

Une énumération peut-elle être utilisée comme paramètre pour un modèle comme celui-ci?

14
IslandCow

Les énumérations peuvent être des paramètres de modèle de la même manière qu'Ints.

enum Enum { ALPHA, BETA };

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

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

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

Mais vous n'avez simplement pas fourni de définition pour E_EnumerationBase::E_EnumerationBase()

Ce n'est pas un problème avec les modèles ou l'héritage. C'est la même chose que si vous écriviez ceci:

struct Foo {
    Foo ();
}
int main () {
    Foo foo;
}
29
spraff

La syntaxe est la même pour les arguments de valeur, comme pour les arguments de nom de type. En gros, vous remplacez simplement typename par le nom de votre 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
8
Sebastian Mach

Vous ne pouvez pas déplacer la définition de la fonction de modèle pour séparer le fichier source. 

Là, il ne serait pas du tout compilé, car les modèles ne peuvent pas être compilés , seules les instances de modèles le peuvent. 

Votre code dans un fichier séparé n'est pas compilé, c'est pourquoi vous n'avez pas de définition pour E_EnumerationBase<TableEventEnum>::E_EnumerationBase(). C'est pourquoi vous obtenez une erreur de l'éditeur de liens.

Il suffit de déplacer tout le code du modèle dans votre en-tête. 

0
Lol4t0

Juste pour la référence, comme vous semblez utiliser Qt: Jetez simplement un coup d'oeil à Q_ENUM, QMetaEnum et QMetaEnum::fromType. Ceux-ci peuvent être utiles pour initialiser votre dictionnaire.

0
Kamajii