c++ - 将enum类变量reinterpret_cast转换为基础类型的引用是否安全?

标签 c++ c++11 reinterpret-cast enum-class

我已经看到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 expression v to type T. If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; if T 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 expression v. Conversions that can be performed explicitly using reinterpret_cast are listed below. No other conversion can be performed explicitly using reinterpret_cast.


(强调我的)
使用引用的重新解释基于5.2.10 / 11中的指针:

11 A glvalue expression of type T1 can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_cast. The result refers to the same object as the source glvalue, but with the specified type. [ Note: That is, for lvalues, a reference cast reinterpret_cast<T&>(x) has the same effect as the conversion *reinterpret_cast<T*>(&x) with the built-in & and * operators (and similarly for reinterpret_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 to T1” is converted to the type “pointer to cv T2”, the result is static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) 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负责使我在初始答案中给出的代码合法,您仍然可以在顶部找到它。

    关于c++ - 将enum类变量reinterpret_cast转换为基础类型的引用是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62312724/

    相关文章:

    C++如何创建指向重载模板函数的函数指针

    c++ - 通过不透明指针获取xml数据

    c++11 - C++ 编译器错误 : “invalid declarator before”

    c++ - C++中所有非成员函数指针的大小是否相同

    c++ - C++中,如何使用单例来保证每个类都有唯一的整数ID?

    没有 C++0x 的 C++ lambda 函数?

    c++ - 错误 : aggregate ‘food_type a’ has incomplete type and cannot be defined

    c++ - 如何避免在 C++11 中触发这种复制构造函数?

    c++ - Reinterpret_cast 与 placement new

    c++ - 通过 void* 进行转换,而不是使用 reinterpret_cast