(怎么样)我可以计算枚举中的项目吗?

时间:2010-01-20 15:37:48

标签: c++ count enumeration

当我有类似

之类的东西时,我想到了这个问题
enum Folders {FA, FB, FC};

并希望为每个文件夹创建一个容器数组:

ContainerClass*m_containers[3];
....
m_containers[FA] = ...; // etc.

(使用地图使用起来更加优雅:std::map<Folders, ContainerClass*> m_containers;

但回到我原来的问题:如果我不想对数组大小进行硬编码,有什么方法可以找出文件夹中有多少项? (不依赖于例如FC是列表中的最后一项,如果我没有弄错的话会允许ContainerClass*m_containers[FC+1]之类的内容。)

7 个答案:

答案 0 :(得分:109)

没有一个好方法可以做到这一点,通常你会在枚举中看到一个额外的项目,即

enum foobar {foo, bar, baz, quz, FOOBAR_NR_ITEMS};

那么你可以这样做:

int fuz[FOOBAR_NR_ITEMS];

虽然还不是很好。

但是当然你会意识到只有枚举中的项目数量是不安全的,例如。

enum foobar {foo, bar = 5, baz, quz = 20};

项目数为4,但枚举值的整数值将超出数组索引范围。使用枚举值进行数组索引并不安全,您应该考虑其他选项。

编辑:根据要求,使特殊条目更加突出。

答案 1 :(得分:31)

对于C ++,有各种type-safe enum techniques可用,其中一些(例如提议但未提交的Boost.Enum)包括对获取枚举大小的支持。

最简单的方法是在C语言和C ++中运行,它采用一种约定,为每个枚举类型声明一个MAX值:

enum Folders { FA, FB, FC, Folders_MAX = FC };
ContainerClass *m_containers[Folders_MAX + 1];
....
m_containers[FA] = ...; // etc.

修改:关于{ FA, FB, FC, Folders_MAX = FC}{FA, FB, FC, Folders_MAX]:我更喜欢将... MAX值设置为枚举的最后一个合法值,原因如下:

  1. 常量的名称在技术上更准确(因为Folders_MAX给出了最大可能的枚举值)。
  2. 就个人而言,我觉得Folders_MAX = FC在其他条目中更突出(更难以在不更新最大值的情况下意外添加枚举值,这是Martin York引用的问题)。
  3. GCC包含有用的警告,例如“未包含在开关中的枚举值”等代码,如下所示。让Folders_MAX == FC + 1打破这些警告,因为你最终会得到一堆...... MAX枚举值,它们永远不应包含在开关中。
  4. switch (folder) 
    {
      case FA: ...;
      case FB: ...;
      // Oops, forgot FC!
    }
    

答案 2 :(得分:7)

STL时尚的特质怎么样?例如:

enum Foo
{
    Bar,
    Baz
};

写一个

std::numeric_limits<enum Foo>::max()

专业化(如果你使用c ++ 11,可能是constexpr)。然后,在您的测试代码中提供任何静态断言来维护std :: numeric_limits :: max()= last_item的约束。

答案 3 :(得分:3)

在枚举结尾处添加一个名为Folders_MAX或类似名称的条目,并在初始化数组时使用此值。

ContainerClass* m_containers[Folders_MAX];

答案 4 :(得分:2)

我喜欢使用枚举作为我的函数的参数。这是提供固定的&#34;选项&#34;的简单方法。这里最高投票答案的问题在于,使用它,客户可以指定一个&#34;无效选项&#34;。作为一个分拆,我建议基本上做同样的事情,但在枚举之外使用一个常量int来定义它们的数量。

enum foobar { foo, bar, baz, quz };
const int FOOBAR_NR_ITEMS=4;

这并不令人愉快,但如果你不更新枚举而不更新常量,它就是一个干净的解决方案。

答案 5 :(得分:1)

我真的没有办法真正了解C ++中枚举中的值的数量。如果您定义的值可能会导致您创建数组太大或太小的情况,那么前面提到的任何解决方案都可以工作,只要您没有定义枚举的值

enum example{ test1 = -2, test2 = -1, test3 = 0, test4 = 1, test5 = 2 }

在这个例子中,当你需要一个包含5个项目的数组时,结果将创建一个包含3个项目的数组

enum example2{ test1 , test2 , test3 , test4 , test5 = 301 }

在这个示例中,当您需要5个项目的数组时,结果将创建301个项目的数组

在一般情况下解决此问题的最佳方法是迭代您的枚举,但据我所知,这不在标准中

答案 6 :(得分:0)

这是在编译时执行此操作的最佳方法。我使用了 here 中的 arg_var count 答案。

#define PP_NARG(...) \
     PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
         PP_ARG_N(__VA_ARGS__)

#define PP_ARG_N( \
          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
         _61,_62,_63,N,...) N
#define PP_RSEQ_N() \
         63,62,61,60,                   \
         59,58,57,56,55,54,53,52,51,50, \
         49,48,47,46,45,44,43,42,41,40, \
         39,38,37,36,35,34,33,32,31,30, \
         29,28,27,26,25,24,23,22,21,20, \
         19,18,17,16,15,14,13,12,11,10, \
         9,8,7,6,5,4,3,2,1,0

#define TypedEnum(Name, ...)                                      \
struct Name {                                                     \
    enum {                                                        \
        __VA_ARGS__                                               \
    };                                                            \
    static const uint32_t Name##_MAX = PP_NARG(__VA_ARGS__);      \
}

#define Enum(Name, ...) TypedEnum(Name, __VA_ARGS__)

声明一个枚举:

Enum(TestEnum, 
Enum_1= 0,
Enum_2= 1,
Enum_3= 2,
Enum_4= 4,
Enum_5= 8,
Enum_6= 16,
Enum_7= 32);

最大值将在此处提供:

int array [TestEnum::TestEnum_MAX];
for(uint32_t fIdx = 0; fIdx < TestEnum::TestEnum_MAX; fIdx++)
{
     array [fIdx] = 0;
}