Felix Dombek
Felix Dombek

Reputation: 14356

C-style cast of enum class to reference of underlying type char

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

Answers (1)

M.M
M.M

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

Related Questions