web-dev-qa-db-ja.com

列挙をテンプレートパラメーターとして使用する

テンプレートクラスを使用して、よく似たいくつかの子クラスに共通の機能を提供したいと思います。唯一のバリエーションは、それぞれが使用する列挙です。

これは親クラスです

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

これは子供の一人です

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

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

これはコンストラクタです

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

リンカはこのエラーを投げています:

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

このようなテンプレートのパラメーターとして列挙を使用できますか?

20
IslandCow

列挙型は、intとまったく同じ方法でテンプレートパラメーターにすることができます。

_enum Enum { ALPHA, BETA };

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

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

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

しかし、あなたは単にE_EnumerationBase::E_EnumerationBase()の定義を提供していません

これはテンプレートや継承の問題ではありません。これを書いた場合と同じです:

_struct Foo {
    Foo ();
}
int main () {
    Foo foo;
}
_
32
spraff

構文は、typename引数の場合と同様に、value引数にも適用されます。基本的に、typenameenumの名前に置き換えるだけです。

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

テンプレート関数の定義を別のソースファイルに移動することはできません。

テンプレートをコンパイルできないであるため、テンプレートインスタンスのみがコンパイルできるため、まったくコンパイルされません。

別のファイルのコードはコンパイルされないため、実際にはE_EnumerationBase<TableEventEnum>::E_EnumerationBase()の定義はありません。これが、リンカエラーが発生する理由です。

すべてのテンプレートコードをヘッダーに移動するだけです。

0
Lol4t0

Qtを使用しているように見えるので、参照用に:Q_ENUMQMetaEnumおよびQMetaEnum::fromType。これらは辞書を初期化するのに便利かもしれません。

0
Kamajii