【问题标题】:Using an enumeration as a template parameter使用枚举作为模板参数
【发布时间】:2012-02-25 08:09:30
【问题描述】:

我想使用一个模板类来为一些非常相似的子类提供一些通用功能。唯一的变化是每个使用的枚举。

这是父类

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()'

枚举可以用作这样的模板的参数吗?

【问题讨论】:

  • 你的构造函数定义在头文件里吗?
  • 不,定义在单独的源文件中。错误显示在链接上。

标签: c++ templates inheritance


【解决方案1】:

枚举可以是模板参数,其方式与 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;
}

【讨论】:

  • 我的错。包含构造函数和方法的实现。
  • 模板中的枚举是否被视为值参数?我想用它作为类型。
  • 如果你想用Foo&lt;MyType&gt; 实例化Foo&lt;typename T&gt;,不管MyType 是类还是枚举或任何其他类型都可以。您也可以使用Foo&lt;integer_contsant_expression&gt; 实例化Foo&lt;int N&gt;,这也可以。当然,前提是替换是有意义的。实现不应该写if(i&lt;T)N value;
  • 这不显示枚举被用作模板参数。这只是显示枚举被强制转换为整数。
  • 现在 (C++11) 也可以使用 enum class 吗?
【解决方案2】:

该语法适用于值参数,就像它适用于类型名称参数一样。基本上,您只需将typename 替换为您的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

【讨论】:

  • 您是否建议枚举用于其价值而不是类型?首先,我试图限制哈希表中的值。
  • “除非你认真理解模板,否则不要写严肃的模板代码”——这有点傲慢。鼓励反馈会更有帮助。
  • @dlchambers:这不是故意的,你是对的。我完全删除了该部分。
【解决方案3】:

您不能将模板函数的定义移动到单独的源文件中。

那里根本不会编译,因为模板不能编译,只有模板实例可以。

您在单独文件中的代码没有被编译,这就是为什么您实际上没有E_EnumerationBase&lt;TableEventEnum&gt;::E_EnumerationBase() 的定义。这就是您收到链接器错误的原因。

只需将所有模板代码移至您的标题。

【讨论】:

  • [枚举] 根本不会被编译" - 枚举不会被编译本身。它们不占用空间在类中。这与需要定义并导致分配的静态 int 形成对比。
【解决方案4】:

仅供参考,因为您似乎使用 Qt:看看 Q_ENUMQMetaEnumQMetaEnum::fromType。这些可能会派上用场来初始化您的字典。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 2021-04-04
    • 1970-01-01
    • 2012-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多