简体   繁体   English

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

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

Why isn't this valid C++?: 为什么这个有效的C ++不是?:

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

GCC 5.4.0 says: 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 };

I can understand why I would get this error if foo were a float , or some struct, or what-not. 我可以理解为什么如果foo是一个float ,或者某个结构,或者什么不是,我会得到这个错误。 But this seems perfectly legit to me in terms of semantics, type safety etc. What am I missing? 但就语义,类型安全等而言,这似乎是完全合法的。我缺少什么?

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

The type-specifier-seq of an enum-base shall name an integral type; 枚举类型说明符-seq应命名为整数类型; any cv-qualification is ignored. 任何cv资格都被忽略了。

Enums are not themselves integral types – [basic.fundamental]/7: 枚举本身不是整数类型 - [basic.fundamental] / 7:

Types bool , char , char16_t , char32_t , wchar_t , and the signed and unsigned integer types are collectively called integral types. 类型boolcharchar16_tchar32_twchar_t以及有符号和无符号整数类型统称为整数类型。

This is accompanied by a non-normative footnote: 这附有一个非规范性的脚注:

Therefore, enumerations are not integral; 因此,枚举不是不可或缺的; however, enumerations can be promoted to integral types as specified in [conv.prom]. 但是,枚举可以提升为[conv.prom]中指定的整数类型。

To achieve the effect I think you're looking for, however, is still simple: 为了达到我认为你正在寻找的效果,仍然很简单:

enum bar : std::underlying_type<foo>::type { best_foo = first_foo };

When you add things to C++, you tend to add the minimium amount that solves a problem. 当您向C ++添加内容时,您倾向于添加解决问题的最小量。

The enum A:int syntax lets you specify exactly how the enum A is stored as an integer. enum A:int语法允许您准确指定enum A如何存储为整数。 That is all it does, and it solves the problem. 这就是它所做的一切,它解决了这个问题。

enum A:B where B is an enum could have many meanings. enum A:B其中B是枚举可能有很多含义。 A could extend B , or A could be a subset of the B underlying type with different names, or A could be an enum strictly restricted to have a subset of the values that can be stored within B , or A could be an enum whose values are restricted to the "hull" of B values. A可以扩展B ,或者A可以是具有不同名称的B基础类型的子集,或者A可以是严格限制为具有可以存储在B内的值的子集的枚举,或者A可以是其值的枚举仅限于B值的“船体”。

Of these, the "same underlying type" solution (with the :int syntax) lines up with enum A:std::underlying_type_t<B> . 其中,“相同的底层类型”解决方案(使用:int语法)与enum A:std::underlying_type_t<B> So there is already a way to do that, and it isn't particularly burdensome. 所以已经有办法做到这一点,并不是特别繁琐。

Until someone makes a suggestion for what enum A:B should mean and convinces enough of the committee, it is unlikely to be permitted. 直到有人对enum A:B应该意味着什么并且说服委员会足够多的人提出建议,这是不可能被允许的。 And when there are multiple different reasonable meanings, this makes it harder for any one meaning to be chosen. 当存在多种不同的合理含义时,这使得任何一种意义的选择变得更加困难。 One would need a strong use case why one particular meaning was best, and why it is worth the effort to put it in the standard. 人们需要一个强有力的用例,为什么一个特定的意义是最好的,为什么值得努力将其纳入标准。

Well, not exactly the same, but I think you could use std::underlying_type : 好吧,不完全相同,但我认为你可以使用std::underlying_type

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

For me it is a logical error to say a enum can be based on an another enum. 对我来说,说枚举可以基于另一个枚举是一个逻辑错误。 If you think that the base is the storage type where the values defined in the enum are stored in, I can not get it as a logic expression to say the storage type is an enum. 如果您认为base是存储在枚举中定义的值的存储类型,那么我无法将其作为逻辑表达式来表示存储类型是枚举。 Because the enum is not only the storage type, it also contains a set of valid values. 因为枚举不仅是存储类型,还包含一组有效值。

If we can write something like: 如果我们可以这样写:

enum A: int { ONE, TWO };

what should mean: 应该是什么意思:

enum B: A{};

Because A defines not only the underlaying type ( I call this the storage type ) but also a set of valid values, should B only a subset of the enum A which means that you can define only values already defined in A? 因为A不仅定义了底层类型(我称之为存储类型)而且还定义了一组有效值,B应该只是枚举A的一个子集,这意味着您只能定义已在A中定义的值?

Is it now valid to say we habe the values ONE,TWO already defined also in B? 现在说我们是否已经在B中定义了两个值? And is it now possible to add more values like: 现在可以添加更多值,例如:

    enum B: A{THREE};

and all valid values are now ONE,TWO,THREE ? 所有有效值现在是一,二,三?

or is the meaning we get only the subset: 或者是我们只得到子集的意思:

    enum B: A{ONE};

which means B can only use values already defined in A. Simply that makes it difficult to me to make a enum a base of another enum. 这意味着B只能使用已在A中定义的值。简单地说,这使得我很难将枚举作为另一个枚举的基础。

If you open that door, you also can also come to the idea that you want to use the underlaying storage type from other kinds of types like bitfields. 如果你打开那扇门,你也可以想到你想要使用其他类型的底层存储类型,比如位域。

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

should then 应该

enum B: A { ONE, TWO };

also be valid? 也有效吗? I believe not! 我不相信! ;) ;)

From the logical point ( my point of view ) the underlaying type of the enum is its storage type. 从逻辑点(我的观点)来看,枚举的底层类型是它的存储类型。 And it makes no sense to make an enum as an underlaying storage type for another enum at all. 将枚举作为另一个枚举的底层存储类型毫无意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM