Reputation: 14356
Is this legal C++ (>=14), resulting in a char
being read and saved into aCode
?
enum class ECode : char { Code1 = 'a' };
std::istream& operator>>(std::istream& aIn, ECode& aCode)
{
return aIn >> (std::underlying_type_t<ECode>&)aCode;
}
I would prefer return aIn >> static_cast<std::underlying_type_t<ECode>&>(aCode)
which is not legal, it seems ("cannot cast to reference of unrelated type".)
However, this very similar line is legal, and is what my C-style cast should be identical to:
return aIn >> *static_cast<char*>(static_cast<void*>(&aCode))
Upvotes: 1
Views: 769
Reputation: 141554
As has been noted in comments, there is no strict aliasing violation because char
can alias any type.
In practice I doubt any real compiler would do anything other than the "obvious" implementation, i.e. give the enum the same size and representation as the underlying type. In which case your reinterpret_cast
would be well-defined and behave as expected.
However the Standard (as of C++17) does not appear to guarantee that.
As far as I can see, it only specifies that any value of the underlying type can be stored in the enum object, and that static_cast
can be used losslessly for values in the range of the underlying type.
There is a language lawyer question here about whether sizeof(ECode) == sizeof(char)
must hold, although the answers seem to say "the standard doesn't actually say so but they probably meant it".
But even if the size is the same there isn't a representation guarantee, e.g. the bits could be stored in some different order and the static_cast
transforms the bits.
In [basic.fundamental] where it specifies the representation of integer types, it even has an explicit footnote saying that enumerations are not integer types.
Upvotes: 2