enum class Foo : int8_t { Bar1,Bar2,Bar3,Bar4,First = Bar1,Last = Bar4 }; for (Foo foo = Foo::First; foo <= Foo::Last; ++reinterpret_cast<int8_t &>(foo)) { ... }
我知道转换为基类的引用是平凡的类的安全.但是,由于枚举类不是事件隐式转换为其底层类型,我不知道上述代码是否以及如何保证在所有编译器中都可以工作.任何线索?
解决方法
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 Reinterpret cast [expr.reinterpret.cast]
1 The result of the expression
reinterpret_cast<T>(v)
is the result of converting the expressionv
to typeT
. IfT
is an lvalue reference type or an rvalue reference to function type,the result is an lvalue; ifT
is an rvalue reference to object type,the result is an xvalue; otherwise,the result is a prvalue and the lvalue-to-rvalue (4.1),array-to-pointer (4.2),and function-to-pointer (4.3) standard conversions are performed on the expressionv
. Conversions that can be performed explicitly usingreinterpret_cast
are listed below. No other conversion can be performed explicitly usingreinterpret_cast
.
(强调我的)
使用引用的重新解释是基于5.2.10 / 11的指针:
11 A glvalue expression of type
T1
can be cast to the type “reference toT2
” if an expression of type “pointer toT1
” can be explicitly converted to the type “pointer toT2
” using areinterpret_cast
. The result refers to the same object as the source glvalue,but with the specified type. [ Note: That is,for lvalues,a reference castreinterpret_cast<T&>(x)
has the same effect as the conversion*reinterpret_cast<T*>(&x)
with the built-in&
and*
operators (and similarly forreinterpret_cast<T&&>(x)
). — end note ] No temporary is created,no copy is made,and constructors (12.1) or conversion functions (12.3) are not called.
这从哪个转变了问题:
reinterpret_cast<int8_t&>(foo)
这是否合法?
*reinterpret_cast<int8_t*>(&foo)
下一站是5.2.10 / 7:
7 An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue
v
of type “pointer toT1
” is converted to the type “pointer to cvT2
”,the result isstatic_cast<
cv
T2*>(static_cast<
cv
void*>(v))
if bothT1
andT2
are standard-layout types (3.9) and the alignment requirements ofT2
are no stricter than those ofT1
,or if either type isvoid
. Converting a prvalue of type “pointer toT1
” to the type “pointer toT2
” (whereT1
andT2
are object types and where the alignment requirements ofT2
are no stricter than those ofT1
) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.
给定3.9 / 9,int8_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 *其中T必须相同(省略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负责将代码合法化,我在初始答案中给出了代码,您仍然可以在顶部找到该代码.