警告:
src/BoardRep.h:49:12: warning: ‘BoardRep::BoardRep::Row::<anonymous struct>::a’
is too small to hold all values of ‘enum class BoardRep::Piece’
[enabled by default]
Piece a:2;
^
枚举:
enum class Piece: unsigned char {
EMPTY,
WHITE,
BLACK
};
使用:
union Row {
struct {
Piece a:2;
Piece b:2;
Piece c:2;
Piece d:2;
Piece e:2;
Piece f:2;
Piece g:2;
Piece h:2;
};
unsigned short raw;
};
对于enum
我同意GCC,它可能必须截断,但这是因为enum
并不真正与整数和预处理器定义分开。但是enum class
要强得多。如果它不够强大,不能假设作为整数的所有Piece
值将在0和2之间(包括0和2),则警告是有意义的。否则海湾合作委员会不必要挑剔,可能值得邮寄清单说“看,这是一个愚蠢的警告”
你可以在2位数据中存储4个不同的值,我只需要3个不同的值,所以任何长度为4或更小的枚举应该很好地适合给定的2位(我的枚举确实“派生”(更好的术语? )来自无符号类型)。如果我有5个或更多那么我会发出警告。
答案 0 :(得分:9)
gcc
发出的警告是准确的,没有必要向邮件列表撰写邮件,要求他们不太可能出现警告。
标准规定,基础类型unsigned char
的枚举不能用长度为2
的位域表示;即使没有具有这种价值的枚举。
标准
即使没有与此值对应的枚举键,枚举的基础值也是有效的,标准只表示要存储在枚举中的合法值必须适合基础类型;它没有说明枚举键中必须存在这样的值。
7.2 枚举声明
[dcl.enum]
7 ... 可以定义一个枚举,该枚举的值不是由任何枚举器定义的。 <子> ... 子>
注意:引用的部分同时出现在C ++ 11和C ++ 14草案中。
注意:措辞陈述相同的内容,但使用不同的术语,可以在[dcl.enum]p6
下的C ++ 03中找到
注意:此帖子中未包含整个[decl.enum]p7
以保留空间。
<强>详情
enum class E : unsigned char { A, B, C };
E x = static_cast<E> (10);
上面我们初始化x
以存储值10
,即使enum class E
的枚举声明中没有枚举键,这仍然存在一个有效的结构。
考虑到上述情况,我们很容易推断10
无法存储在长度为2
的位字段中,因此gcc
的警告只是准确的......我们是可能试图将值存储在我们无法表示的位域中。
示例强>
enum class E : unsigned char { A, B, C };
struct A {
E value : 2;
};
A val;
val.value = static_cast<E> (10); // OMG, OPS!?
答案 1 :(得分:1)
根据C ++标准
8对于其基础类型是固定的枚举,其值为 枚举是基础类型的值。
因此,枚举值在
范围内std::numeric_limits<unsigned char>::min() - std::numeric_limits<unsigned char>::max()
位字段a定义为
Piece a:2;
无法保存枚举的所有值。
如果要定义没有固定基础类型的无范围枚举,则其值的范围将为
0 - 2