【问题标题】:How to deduce array size from an enum template argument?如何从枚举模板参数推断数组大小?
【发布时间】:2011-06-27 07:03:57
【问题描述】:

我应该如何更改下面的代码,以使Array<Index> array; 足够,并从枚举中自动推导出SIZE
即使枚举发生变化,也保证它包含 SIZE 指的是正确的大小。

template <typename Enum, int N>
class Array {

public:
    int& operator[](Enum index) { return array[index]; }

private:
    int array[N];
};

enum Index { X, Y, SIZE };

int main() {

    Array<Index, SIZE> array;

    array[X] = 1;

    return 0;
}

更新: 至于“Array 表示您正在创建一个 Type 对象数组”(Jerry)和“类模板的名称有点误导”(Nawaz):实际上我正在创建 CustomSqlQueryModel。以上只是简化的代码,仅此而已。 Jerry 和 Nawaz 是正确的:这种简化的代码是不幸的。

【问题讨论】:

  • 你不能计算一个枚举中的枚举元素个数。
  • 是的,但在我的情况下,它保证有一个 SIZE 指代元素的数量。
  • 我想我不明白这个问题。

标签: c++ arrays templates enums


【解决方案1】:

如前所述,我认为你不能。但是,如果您将其更改为:

struct Index { 
    enum { X, Y, SIZE};
};

那么你的模板可能是这样的:

template <class Enum>
class Array { 
// ...

private:
    int array[Enum::SIZE];
};

...如果您作为Enum 传递的类型不包含一些名为SIZE 的正常量,则实例化将无法编译。出于手头的目的,您确实更喜欢 Index 是命名空间,但由于命名空间不是类型,我认为您不能将其用作模板参数。

不过,我应该补充一点,我不确定我是否喜欢这个想法——大多数人会认为 Array&lt;type&gt; 意味着您正在创建一个 Type 对象数组,这显然是什么完全不一样……

【讨论】:

  • 谢谢。 struct 方法的问题在于您必须编写: array[Enum::X] = 1;这很丑:(至于“Array 意味着你正在创建一个 Type 对象数组”你是对的,实际上我正在创建 CustomSqlQueryModel。也许我应该想出一个更好的简化示例代码.
  • C++0x 的新枚举将允许您传递枚举类型并直接说Enum::Size,而无需包装在类中
  • @Johannes Cool :) 请将其发布为答案!
  • @Ali:你还得说Enum::X,因为它们是作用域枚举,尽管 IMNSHO 这是一个的东西。在枚举数之前声明 enum 类型会为读者提供上下文。
  • @Matthieu 你能详细说明一下吗?恐怕我不遵守:(
【解决方案2】:

您可以编写一个特征类。每次定义新的枚举类型时都需要做一些额外的工作,但对于用户代码中每次出现的 Array 不需要额外的工作:

template<class Enum>
struct ArrayTraits;

template<class Enum>
struct Array {
  int& operator[](Enum index) { return array[index]; }

private:
  int array[ArrayTraits<Enum>::size];
};

enum Index { X, Y, SIZE };

template<>
struct ArrayTraits<Index> {
  enum { size = SIZE };
};


int main() {
  Array<Index> array;
  array[X] = 1;
  return 0;
}

这样做的一个好处是,只要您知道如何获得最大大小,您就可以专门针对您无法控制的外部枚举的特征。

【讨论】:

  • @Ali:另外,如果您正在为这些枚举使用代码生成(例如,从某种模式生成),那么这个样板特征很容易保持更新。
【解决方案3】:

如果您只希望 size 成为模板参数,而不是 type ,从您的示例看来, type 的数组总是int,那你为什么不实现这个:

template <int size>
class Array {

public:
    int& operator[](int index) { return array[index]; }

    //Note this addition!
    int operator[](int index) const { return array[index]; }
private:
    int array[size];
};

int main() {

    Array<10> array;

    array[0] = 1;
    array[1] = 2;

    return 0;
}

注意这个添加:如果你也实现operator[] 的const 版本会更好,这样const Array&lt;&gt; 可以使用它来访问数组元素,否则你的类将不适用于const Array&lt;&gt;

【讨论】:

  • 我需要枚举模板参数,它使访问数组元素变得安全。 int-s 没有这样的安全性。无论如何感谢您的回答。
  • @Ali:你在说什么安全?以及它是如何通过枚举实现的?请解释一下。
  • @Nawaz 是的,如果你可以投射,但这是你的责任,就像投射时一样。正如我在更新中所写,我使用这个数组来访问数据库表中的列,我不想为此使用 int-s 和幻数,我需要枚举中的列名。
  • @Nawaz 是的,但我不写循环。我用它来访问数据库表中具有有意义名称的列。
  • @Nawaz 我可以重复一遍:我正在创建自定义 SQL 查询,将带有列 NAMES(而不是类型)的模板参数枚举传递给它是非常好的。我没有遍历任何数组。我的代码只是一个简化的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多