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

Using `reinterpret_cast` on an enum class - valid or undefined behavior?

本文关键字:有效 未定义 cast 枚举 reinterpret      更新时间:2023-10-16
#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;
}

艾德酮

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

标准有点不清楚:

3.10 左值和右值 [基本值]

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

[...]

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

[...]

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

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

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

强烈暗示它将根据程序中没有发生此类混叠的假设进行优化。