#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;
}
Is this code guaranteed to always work? Or is it undefined behavior?
Best Answer
The standard is a bit unclear:
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
strongly hinting that it will optimise on the assumption that no such aliasing takes place in your program.