我需要使用作用域枚举,以便我可以将它们作为特定类型传递给我们的序列化程序。我为Enum1
的枚举成员提供了显式整数值。
我已将两个与上述描述相匹配的范围内的枚举放入一个位域
enum class Enum1 {
value1 = 0x0,
value2 = 0x1,
value3 = 0x2
};
enum class Enum2 {
value1 = 0x0,
value2,
value3,
// ...
value14
};
struct Example {
Enum1 value1 : 2;
Enum2 value2 : 6;
}
现在无论我在哪里使用Example
类型,我都会收到警告“'Example :: value1'太小而无法容纳'Enum1'的所有值”,对于Enum2
也是如此。请注意,我们定义的值不是这种情况,我们并不关心所有的值超出这些值。
这在我们的构建过程中是一个非常严重的分心 - 项目庞大而复杂,我们不希望扫描其中的许多警告(并且有很多)。
我找了一个GCC(G ++)标志来禁用特定警告。有没有我可以通过命令行?理想情况下,如果可能的话,我会使用警告编译指示在本地禁用它。
此时几乎没有更改代码结构的余地,但我们确实可以删除这些虚假警告。
编辑:添加了标识符已更改的范围化枚举。
答案 0 :(得分:12)
问题是作用域枚举始终具有整体底层类型。默认情况下,它是int
,但您可以将其更改为任何其他整数类型,例如unsigned char
。
不幸的是,您无法将基础类型更改为位字段,因为它们不是真正的C ++类型。
您可以尝试禁用警告,但快速浏览G ++代码会显示这些行(gcc/cp/class.c:3468
):
else if (TREE_CODE (type) == ENUMERAL_TYPE
&& (0 > (compare_tree_int
(w, TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type))))))
warning_at (DECL_SOURCE_LOCATION (field), 0,
"%qD is too small to hold all values of %q#T",
field, type);
此处的关键是拨打warning_at(...)
而不是warning(OPT_to_disable_the_warning, ...)
。所以目前没有选项可以禁用它。除了自己重新编译编译器!
值得注意的是CLang ++ - 3.7.1没有警告它。
答案 1 :(得分:2)
我记得,无论定义了什么枚举常量,具有声明的基础类型的枚举都可以保存该类型的任何值。既然你可以说
val= enum2{148}
并期望它正常工作,这种情况的警告似乎是正确的。你并没有声明一个基类型,而且从历史上看,这意味着枚举只能保证足够大,以保持最低到最高枚举常数给出的值范围。所以我希望这里没有任何警告。也许新的enum class
也期望一个完整的范围,即使底层类型是自动确定的(或者编译器认为它确实如此)?您可以尝试使用纯旧的语法枚举,看看它是否有所不同。