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

Why can't I have an enum as the underlying type of another enum?

本文关键字:枚举 另一个 类型 一个 不能 为什么      更新时间:2023-10-16

为什么这不是有效的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,或一些结构体,或什么不是。但在我看来,这在语义、类型安全等方面是完全合法的。我错过了什么?

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

枚举基类型说明符seq命名整型;任何简历资格都将被忽略。

枚举本身不是整型& & &;(basic.fundamental)/7:

类型boolcharchar16_tchar32_twchar_t以及有符号和无符号整数类型统称为整型

这伴随着一个非规范的脚注:

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

然而,要达到我认为你正在寻找的效果,仍然很简单:
enum bar : std::underlying_type<foo>::type { best_foo = first_foo };

当你向c++中添加东西时,你倾向于添加解决问题的最小量。

enum A:int语法允许您精确地指定如何将enum A存储为整数。这就是它所做的,它解决了问题。

enum A:B(其中B为enum)可以有多种含义。A可以是B的扩展,或者A可以是B底层类型的一个不同名称的子集,或者A可以是一个严格限制的枚举,其值的子集可以存储在B中,或者A可以是一个枚举,其值被限制为B值的"外壳"。

其中,"相同底层类型"解决方案(使用:int语法)与enum A:std::underlying_type_t<B>一致。因此,已经有一种方法可以做到这一点,而且它不是特别繁重。

除非有人提出enum A:B应该是什么意思的建议,并说服委员会足够的人,否则不太可能被允许。当有多种不同的合理含义时,这使得选择任何一种含义变得更加困难。我们需要一个强有力的用例来说明为什么某个特定的含义是最好的,以及为什么值得努力将其放入标准中。

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

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

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

如果我们可以这样写:

enum A: int { ONE, TWO };

含义:

enum B: A{};

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

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

    enum B: A{THREE};

和所有有效值现在是ONE,TWO,THREE ?

or的意思是我们只能得到子集:

    enum B: A{ONE};

这意味着B只能使用a中已经定义的值,这使得我很难将一个枚举作为另一个枚举的基数。

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

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

应该

enum B: A { ONE, TWO };

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

从逻辑的角度来看(我的观点),枚举的底层类型是它的存储类型。将一个enum作为另一个enum的底层存储类型根本没有意义。