为什么可以';我有一个枚举作为另一个枚举的基础类型吗? 为什么这个C++不是有效的? enum foo : unsigned { first_foo, second_foo }; enum bar : foo { best_foo = first_foo };

为什么可以';我有一个枚举作为另一个枚举的基础类型吗? 为什么这个C++不是有效的? enum foo : unsigned { first_foo, second_foo }; enum bar : foo { best_foo = first_foo };,c++,c++11,enums,subclassing,C++,C++11,Enums,Subclassing,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 }; 如果foo是一个float,或者某个结构,或者什么都不是,我可以理解为什么会出现这个错误。但这在语义、类型安全性等方面对我来说似乎完全合法。我缺少什么?嗯,不完全相同,但我认为您可以使用: enumfoo:unsigne

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 };

如果
foo
是一个
float
,或者某个结构,或者什么都不是,我可以理解为什么会出现这个错误。但这在语义、类型安全性等方面对我来说似乎完全合法。我缺少什么?

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

enumfoo:unsigned{first_foo,second_foo};
枚举栏:std::底层类型{best_foo=first_foo};
C++11[dcl.enum]/2:

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

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

类型
bool
char
char16\u t
char32\u t
wchar\u t
,有符号和无符号整数类型统称为整数类型

随附非规范性脚注:

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

然而,要达到我认为您想要的效果,仍然很简单:

enum bar : std::underlying_type<foo>::type { best_foo = first_foo };
enum bar:std::底层类型::类型{best\u foo=first\u foo};

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

如果我们能写下这样的东西:

enum A: int { ONE, TWO };
这意味着什么:

enum B: A{};
因为A不仅定义了参考底图类型(我称之为存储类型),而且还定义了一组有效值,所以B是否应该仅定义枚举A的子集(这意味着只能定义A中已定义的值)

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

    enum B: A{THREE};
所有的有效值现在都是1,2,3

或者我们只得到子集的意思是:

    enum B: A{ONE};
这意味着B只能使用A中已经定义的值。这使得我很难将一个枚举作为另一个枚举的基础

如果打开这扇门,您还可能会想到,您希望使用来自其他类型(如位字段)的参考底图存储类型

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

enum B: A { ONE, TWO };
也有效吗?我相信不是


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

< P>当您将东西添加到C++时,您倾向于添加最小量来解决问题。

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

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

其中,“相同的基础类型”解决方案(使用
:int
语法)与
枚举A:std::基础类型匹配。因此,已经有一种方法可以做到这一点,而且并不特别麻烦


除非有人就枚举a:B的含义提出建议,并使委员会足够信服,否则不太可能允许这样做。当存在多个不同的合理含义时,任何一个含义都很难被选择。我们需要一个强有力的用例来说明为什么一个特定的含义是最好的,以及为什么值得努力将其纳入标准。

@einpoklum好吧,你在问题中没有提到这一点,那么我怎么可能知道呢?我也不知道为什么它不能满足你的需求;无论怎样,常规的
enum
在底层类型转换方面都非常弱。好吧,这是直接的形式原因-但是为什么类型说明符seq必须命名一个整数类型,而不是整数类型或枚举类型?@einpoklum:对于此类站点来说,这是一个影响深远的问题。我不在C++委员会,所以我不确定我怎么知道。嗯,有时委员会成员或关注委员会工作的人经常访问这个网站并回答问题。比亚恩甚至回答过我一次。@einpoklum我怀疑答案是他们不认为这很重要。如果你想改变它,写一个建议:)。受这个答案的启发,我检查整型的语法。[积分类型(另见std::is_integral)]为什么?因为标准是这么说的。:)@泽雷格斯:通常的原因是,他们的建议被接受了。对我来说,说一个枚举可以基于另一个枚举是一个逻辑错误。如果您认为基是存储枚举中定义的值的存储类型,我无法将其作为逻辑表达式来表示存储类型是枚举。因为枚举不仅是存储类型,它还包含一组有效值。那么,基于其他枚举的枚举应该是什么呢?仅是参考底图枚举的子集,因为所有其他值都没有在参考底图枚举中定义?为什么枚举不应该基于同样表示某种整型存储类型的位字段?@Klaus:看看我的动机。但你们提出了一个有效的观点,也许你们应该把它作为一个答案。“应该只是枚举a的一个子集”?是的,实际上我也这么认为。@einpoklum如果它只能是一个子集,那么它与从结构/类派生相反。因为您只能在派生类中扩展基类。那么这符合逻辑吗
enum B: A { ONE, TWO };