在枚举类上使用`reinterpret_cast` - 有效或未定义的行为?

时间:2015-03-15 21:23:22

标签: c++ language-lawyer c++14 reinterpret-cast enum-class

#include <iostream>
#include <cassert>
#include <type_traits>

template<typename T> using Underlying = std::underlying_type_t<T>;

enum class ETest : int
{
    Zero = 0,
    One = 1,
    Two = 2
};

template<typename T> auto& castEnum(T& mX) noexcept
{
    // `static_cast` does not compile
    // return static_cast<Underlying<T>&>(mX);

    return reinterpret_cast<Underlying<T>&>(mX);
}

int main()
{
    auto x(ETest::Zero);
    castEnum(x) = 1;
    assert(x == ETest::One);

    return 0;
}

ideone

此代码是否始终有效?还是未定义的行为?

1 个答案:

答案 0 :(得分:1)

标准有点不清楚:

  

3.10 Lvalues和rvalues [basic.lval]

     

10如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:

     

[...]

     

(10.4) - 与对象的动态类型对应的有符号或无符号类型,

     

[...]

这可以合法地解读为对应于枚举类型的有符号或无符号类型是它的基础类型,但我认为这意味着只涵盖 通过其他类型访问整数类型-signed对应类型,枚举类型的基础类型不计为与该枚举类型对应的(un)signed类型。

至少GCC同意这一点:它为

提供了别名警告
enum E : int { };
int f(E e) { return *(int *) &e; }
warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

强烈暗示,如果您的程序中没有出现此类别名,它会进行优化。