5

I'm looking through n3690, a draft of the upcoming C++14 standard, and I see in section 7.2 paragraph 9:

Two enumeration types are layout-compatible if they have the same underlying type.

However, I can't find anything that says an enumeration type is layout-compatible with its underlying type. To me it seems obvious that this should follow given the reasonable semantics for what "underlying type" means, but is it actually guaranteed by the standard?

Praetorian
  • 106,671
  • 19
  • 240
  • 328
Shea Levy
  • 5,237
  • 3
  • 31
  • 42
  • In C, this is guaranteed, and C++ requires support for mixing with C code, which cannot be implemented correctly unless C++ uses the same representation as C. I'd like to see a more direct answer, though, especially as this doesn't really capture all aspects of layout compatibility. –  Feb 22 '14 at 23:28

1 Answers1

3

NO, there is no black-letter quote from the Standard that specifies this. The closest that one can get is point 7 of that same paragraph

7 [...] the underlying type is an integral type that can represent all the enumerator values defined in the enumeration. If no integral type can represent all the enumerator values, the enumeration is ill-formed. [...]

Furthermore, 4.5 Integral promotions [conv.prom] says

4 A prvalue of an unscoped enumeration type whose underlying type is fixed (7.2) can be converted to a prvalue of its underlying type.

As pointed out in the comments, there could be (devious IMO) implementations that have different endianess between an enum and its underlying type. That would be a Quality of Implementation issue. For all practical purposes, layout-compatibility should be expected.

TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • 1
    This guarantees that you can `static_cast` between the two, but AFAIK it doesn't imply layout-compatibility in the strict sense (e.g. as required for type punning through a union). – dyp Feb 22 '14 at 23:22
  • @dyp [conv.prom]/4 has a more direct quote. – TemplateRex Feb 22 '14 at 23:42
  • Maybe I'm just paranoid, but I think *convertibility* and/or equality of valid ranges isn't *enough* for some gcc with `-fstrict-aliasing`. E.g. if for some implementation, `short` has the same size as `int`, that doesn't make them (automatically) layout-compatible in the sense `union { short s; int i; } u; u.s = 42; cout << u.i;` – dyp Feb 22 '14 at 23:48
  • I take that back -- it *is* enough for gcc with `-fstrict-aliasing`. [See it live](http://coliru.stacked-crooked.com/a/ff3c5f17bb4eda9b) – dyp Feb 22 '14 at 23:51
  • 3
    A hypothetical extremely evil implementation might make enumeration types big-endian, but the underlying integer type little-endian. There is nothing in this answer that says such an implementation is invalid, and I cannot find anything in the standard either other than the general C compatibility requirements I noted in a comment on the question. –  Feb 23 '14 at 00:17
  • @hvd and endian-conversion are allowed when doing integral promotions? Even if that is true, it would be a sever QoI issue. – TemplateRex Feb 23 '14 at 08:51
  • @TemplateRex Sure, why not? Integral promotions are about values, not representation, which is why a value of an 8-bit type can promote to a value of a 32-bit type on common implementations, even though those use different representations too. But I didn't intend for that to be a realistic implementation, more an example of how the standard is somewhat under-specified by allowing such an implementation. –  Feb 23 '14 at 09:12
  • @hvd I still fail to see how endianness can switch: the underlying type itself is defined as the type that can represent all enumeration values. Absent an actual counter example I would believe that compatibility is guaranteed. – TemplateRex Feb 23 '14 at 14:52
  • @TemplateRex I think there's some miscommunication. What do you mean by "compatibility"? Given `enum E e` with an underlying type of `int`, are you talking about `static_cast(e)`, or about `reinterpret_cast(e)`? The standard explicitly requires the former, and that still works even if there's a difference in endian-ness, but the latter is more relevant for layout-compatibility, and left largely unaddressed in the standard. –  Feb 23 '14 at 15:04
  • Forget endianness, they could deviously be different sizes, or an implementation could stick an RTTI identifier into all enumerations. That said, I think this is generally considered to be a defect in the standard. – Potatoswatter Feb 24 '14 at 21:41
  • @Potatoswatter You're right. I got confused with `wchar_t`/`char16_t`/`char32_t`, which also have an underlying type, but do have stronger compatibility requirements. –  Feb 25 '14 at 20:42