++
如果你真的想迭代它的值,你可能想为你的枚举重载运算符:
Foo& operator++( Foo& f )
{
using UT = std::underlying_type< Foo >::type;
f = static_cast< Foo >( static_cast< UT >( f ) + 1 );
return f;
}
并使用
for (Foo foo = Foo::First; foo != Foo::Last; ++foo)
{
...
}
要回答是否reinterpret_cast
允许的问题,一切从 5.2.10/1 开始:
5.2.10 重新解释演员表 [expr.reinterpret.cast]
1表达式reinterpret_cast<T>(v)
的结果是将表达式转换v
为类型的结果T
。如果T
是左值引用类型或对函数类型的右值引用,则结果为左值;如果T
是对对象类型的右值引用,则结果是一个 xvalue;否则,结果为纯右值,并且对表达式执行左值到右值 (4.1)、数组到指针 (4.2) 和函数到指针 (4.3) 的标准转换v
。下面列出了可以显式执行的转换。reinterpret_cast
不能使用 显式执行其他转换reinterpret_cast
。
(强调我的)
使用引用的重新解释基于 5.2.10/11 中的指针:
11如果“pointer to”类型T1
的表达式可以使用. 结果引用与源 glvalue 相同的对象,但具有指定的类型。[注意:也就是说,对于左值,引用强制转换与使用内置和运算符的转换具有相同的效果(对于 也是类似的)。—尾注] 不创建临时文件,不复制副本,也不调用构造函数 (12.1) 或转换函数 (12.3)。T2
T1
T2
reinterpret_cast
reinterpret_cast<T&>(x)
*reinterpret_cast<T*>(&x)
&
*
reinterpret_cast<T&&>(x)
这改变了这个问题:
reinterpret_cast<int8_t&>(foo)
这是否合法:
*reinterpret_cast<int8_t*>(&foo)
下一站是 5.2.10/7:
7对象指针可以显式转换为不同类型的对象指针。当v
“pointer to T1
”类型的纯右值转换为“pointer to cv T2
”类型时,结果是如果和都是标准布局类型(3.9)并且 的对齐要求不比 的更严格,或者如果任一类型是。将“pointer to”类型的纯右值转换为“pointer to ”类型(其中和是对象类型,其中 的对齐要求不比 的 更严格)并返回其原始类型会产生原始指针值。未指定任何其他此类指针转换的结果。static_cast<
cv
T2*>(static_cast<
cv
void*>(v))
T1
T2
T2
T1
void
T1
T2
T1
T2
T2
T1
鉴于 3.9/9int8_t
和您的枚举类型都是标准布局类型,问题现在转换为:
*static_cast<int8_t*>(static_cast<void*>(&foo))
这是你不走运的地方。static_cast
在 5.2.9 中定义,没有什么可以使上述合法 - 事实上 5.2.9/5 明确暗示它是非法的。其他条款没有帮助:
- 5.2.9/13 要求
T*
-> void*
-> T*
whereT
必须相同(省略cv)
- 5.2.9/9 和 5.2.9/10 不是关于指针,而是关于值
- 5.2.9/11 是关于类和类层次结构的
- 5.2.9/12 是关于类成员指针的
我的结论是你的代码
reinterpret_cast<int8_t&>(foo)
是不合法的,它的行为没有被标准定义。
另请注意,上述 5.2.9/9 和 5.2.9/10 负责使我在最初的答案中给出的代码合法,您仍然可以在顶部找到这些代码。