为什么我不能将枚举作为另一个枚举的基础类型?

时间:2016-11-15 10:05:50

标签: c++ c++11 enums subclassing

为什么不是这个有效的C ++?:

enum foo : unsigned { first_foo, second_foo };
enum bar : foo { best_foo = first_foo };

GCC 5.4.0说:

/tmp/a.cpp:3:16: error: underlying type ‘foo’ of ‘bar’ must be an integral type
     enum bar : foo { best_foo = first_foo };

我理解为什么如果foofloat,或某个结构,或者什么不是,我会收到此错误。但在语义,类型安全等方面,这对我来说似乎是完全合法的。我缺少什么?

4 个答案:

答案 0 :(得分:8)

C ++ 11 [dcl.enum] / 2:

  

enum-base type-specifier-seq 应命名为整数类型;任何cv资格都会被忽略。

枚举本身不是整数类型 - [basic.fundamental] / 7:

  

类型public List<Category> GetCategoryByID(int menuID) { return db.Table<Category>().Where(x => x.menu_ID == menuID).ToList(); } boolcharchar16_tchar32_t以及有符号和无符号整数类型统称为 integral 类型。

这附有一个非规范的脚注:

  

因此,枚举不是不可或缺的;但是,枚举可以提升为[conv.prom]中指定的整数类型。

为了达到我认为你正在寻找的效果,但仍然很简单:

wchar_t

答案 1 :(得分:4)

当您向C ++添加内容时,您倾向于添加解决问题的最小数量。

enum A:int语法允许您准确指定enum A如何存储为整数。就是这样,它解决了这个问题。

enum A:B其中B是一个枚举可能有很多含义。 A可以扩展B,或A可以是具有不同名称的B基础类型的子集,或者A可以是严格限制为枚举的枚举可以存储在BA中的值的子集可以是枚举,其值仅限于B值的“外壳”。

其中,“相同的基础类型”解决方案(使用:int语法)与enum A:std::underlying_type_t<B>对齐。所以已经有办法做到这一点,并不是特别沉重。

在有人对enum A:B应该表达的内容提出建议并说服委员会足够多之前,不太可能允许这样做。当存在多种不同的合理含义时,这使得任何一种意义的选择变得更加困难。人们需要一个强有力的用例,为什么一个特定的意义是最好的,为什么值得努力将其纳入标准。

答案 2 :(得分:3)

嗯,不完全一样,但我认为你可以使用std::underlying_type

enum foo : unsigned { first_foo, second_foo };
enum bar : std::underlying_type_t<foo> { best_foo = first_foo };

答案 3 :(得分:3)

对我而言,说枚举可以基于另一个枚举是一个逻辑错误。如果您认为base是存储在枚举中定义的值的存储类型,那么我无法将其作为逻辑表达式来表示存储类型是枚举。因为枚举不仅是存储类型,还包含一组有效值。

如果我们能写出类似的东西:

enum A: int { ONE, TWO };

应该是什么意思:

enum B: A{};

因为A不仅定义了底层类型(我称之为存储类型)而且定义了一组有效值,B应该只是枚举A的一个子集,这意味着您只能定义已经在A中定义的值吗? / p>

现在说我们是否已经在B中定义了两个值? 现在可以添加更多值,如:

    enum B: A{THREE};

并且所有有效值现在都是一,二,三?

或者我们只获得子集的含义:

    enum B: A{ONE};

这意味着B只能使用已经在A中定义的值。简单地说,这使得我很难将枚举作为另一个枚举的基础。

如果你打开那扇门,你也可以想到你想要使用其他类型的底层存储类型,比如位域。

struct A { unsigned int a : 3; unsigned int B: 2; };
那么

应该

enum B: A { ONE, TWO };

也有效吗?我不相信! ;)

从逻辑点(我的观点)来看,枚举的底层类型是它的存储类型。将枚举作为另一个枚举的底层存储类型毫无意义。