Using an enumeration as a template parameter

79,111

Solution 1

Enumerations can be template parameters in exactly the same way that ints can.

enum Enum { ALPHA, BETA };

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

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

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

But you simply haven't provided a definition for E_EnumerationBase::E_EnumerationBase()

This isn't a problem with templates or inheritence. It's the same as if you written this:

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

Solution 2

The syntax goes for value arguments like it is for typename arguments. Basically, you just replace typename with the name of your 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

Solution 3

You cannot move definition of template function to separate source file.

There it wouldn't be compiled at all, because templates can't be compiled, only template instances can.

Your code in separate file isn't get compiled, that's why you actually have no definition for E_EnumerationBase<TableEventEnum>::E_EnumerationBase(). That's why you get linker error.

Just move all template code to your header.

Share:
79,111
IslandCow
Author by

IslandCow

Updated on July 09, 2022

Comments

  • IslandCow
    IslandCow almost 2 years

    I would like to use a template class to provide some common functionality to some child classes that are very similar. The only variation is the enumeration that each uses.

    This is the parent class

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

    This is one of the children

    enum TableEventEnum {
        NO_VALUE = 0,
        ATTRACT = 1,
        OPEN = 2,
        CLOSED = 3
    };
    
    class E_TableEvent : public E_EnumerationBase<enum TableEventEnum>
    {
    public:
        E_TableEvent();
    };
    

    This is the constructor

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

    The linker is throwing this error:

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

    Can an enumeration be used as the parameter to a template like this?