1
#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

Is this code guaranteed to always work? Or is it undefined behavior?

4

1 回答 1

1

标准有点不清楚:

3.10 左值和右值 [basic.lval]

10 如果程序尝试通过非下列类型之一的左值访问对象的存储值,则行为未定义:

[...]

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

[...]

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

至少 GCC 同意这一点:它给出了一个别名警告

enum E : int { };
int f(E e) { return *(int *) &e; }
警告:取消引用类型双关指针将破坏严格别名规则 [-Wstrict-aliasing]

强烈暗示它将在您的程序中没有发生此类别名的假设下进行优化。

于 2015-03-15T21:57:33.737 回答