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

北战南征 提交于 2020-06-17 06:47:51

问题


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


回答1:


The standard is a bit unclear:

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,

[...]

This could be legitimately read as saying that the signed or unsigned type corresponding to an enumeration type is its underlying type, but I'd think this is meant to cover only accessing integer types through their other-signed corresponding type, that the underlying type of an enumeration type does not count as the (un)signed type corresponding to that enumeration type.

At least GCC agrees with this: it gives an aliasing warning for

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

strongly hinting that it will optimise on the assumption that no such aliasing takes place in your program.



来源:https://stackoverflow.com/questions/29066335/using-reinterpret-cast-on-an-enum-class-valid-or-undefined-behavior

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!