我已经看到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/11中的指针:

从而改变了这个问题:
reinterpret_cast<int8_t&>(foo)
是否合法:
*reinterpret_cast<int8_t*>(&foo)
下一站是5.2.10/7:

给定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/19476818/

    10-10 21:38
    查看更多