c++ - 在枚举类上使用 `reinterpret_cast` - 有效还是未定义的行为?

标签 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

这段代码能保证始终有效吗?或者这是未定义的行为?

最佳答案

标准有点不清楚:

3.10 Lvalues and rvalues [basic.lval]

10 If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

[...]

(10.4) -- a type that is the signed or unsigned type corresponding to the dynamic type of the object,

[...]

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

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

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

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

关于c++ - 在枚举类上使用 `reinterpret_cast` - 有效还是未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29066335/

相关文章:

c++ - 将 C++11 线程操作与 QThread 操作混合

c++ - 更大的运算符 ">"是否满足严格的弱排序?

c++ - 如何在ChaiScript 中注册重载的模板成员函数?

sockets - 哪些协议(protocol)值与 socket() 中的哪些域和类型组合兼容?

c++ - 使用循环从外部文件填充结构

c++ - 在 C++ 程序中使用 C 头文件

c++ - 禁用没有宏的 C++ 代码

c++ - 推导第一个模板参数与默认的其他模板参数

C++ 临时变量的生命周期因绑定(bind)到引用成员而缩短?

c++ - 无法将 std::bind 的返回值转换为 void 函数指针