我已经看到reinterpret_cast
用于将增量应用于枚举类,并且我想知道这种用法在标准C++中是否可以接受。
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明确表明它是非法的。其他子句无济于事:T*
-> void*
-> T*
,其中T
必须相同(省略cv)我的结论是您的代码
reinterpret_cast<int8_t&>(foo)
不合法,其行为未由标准定义。还要注意,上述5.2.9 / 9和5.2.9 / 10负责使我在初始答案中给出的代码合法,您仍然可以在顶部找到它。
关于c++ - 将enum类变量reinterpret_cast转换为基础类型的引用是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62312724/