20

I just can't see why the size of the enumeration is relevant for the compiler while the size of the class is not.

My code example:

class A;
enum E;   // must be enum E : int; in order to compile 

void f(const A & param);
void f(const E & param);

I'm talking here of standard C++ compilers. I know that MSVC let it compile and works fine. So the question is:

Why this has not been standardized?

psmears
  • 26,070
  • 4
  • 40
  • 48
nyarlathotep108
  • 5,275
  • 2
  • 26
  • 64
  • It is even messier than you think: I think msvc forces unsized enums to 32 bits. – Yakk - Adam Nevraumont Mar 13 '15 at 14:51
  • @Yakk i think that too. But why the size should be relevant anyway? – nyarlathotep108 Mar 13 '15 at 15:03
  • I'm not sure it's the size that's relevant, but rather, the something clearly not C++03 syntax. Instead of a size you can use a scoped enumeration, with one of the keywords struct or class. Relevant standardese: " An opaque-enum-declaration declaring an unscoped enumeration shall not omit the enum-base." – Cheers and hth. - Alf Mar 13 '15 at 15:03
  • Not sure if relevant, but it does occur to my associative circuit that the only case the standard doesn't allow, is the up till then existing practice (mainly as the Visual C++ language extension). So, maybe politics. – Cheers and hth. - Alf Mar 13 '15 at 15:11
  • I have a very vague memory about reading about this being standardized. Something about it basically being what was easy for compiler writers. Ie, `enum class X:type;` and `enum class X:type { values... };` where low hanging fruit (easy to implement, and useful). What you describe might not be (as we now have a compiler having an enum that it doesn't know the size of, which wasn't possible prior to the change) as easy. I do not have faith in this memory. – Yakk - Adam Nevraumont Mar 13 '15 at 15:16

2 Answers2

11

This has been standardized, proposal 2764: Forward declaration of enumerations (rev. 3) allowed the forward declaration of enums if you specify the underlying type, whereas before this was not possible.

The main reason is that when the underlying type is not specified the size is implementation defined and can depend on the enumerator values. From the draft C++11 standard section 7.2 [dcl.enum]:

For an enumeration whose underlying type is not fixed, 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. It is implementation-defined which integral type is used as the underlying type except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int or unsigned int. If the enumerator-list is empty, the underlying type is as if the enumeration had a single enumerator with value 0.

When passing by value it makes sense that not knowing the underlying type is an issue, but why is it an issue when it is a pointer or reference? This matters since apparently on some architectures, char* and int* can have different sizes as mentioned in this comp.lang.c++ discussion: GCC and forward declaration of enum:

[...] While on most architectures it may not be an issue, on some architectures the pointer will have a different size, in case it is a char pointer. So finally our imaginary compiler would have no idea what to put there to get a ColorsEnum*[...]

We have the following stackoverflow answer for reference which describes the case where char* can be larger than int*, which backs up the assertion in the discussion above.

Some more details on the possible sizes of pointers it looks like char * and void * are the two main exceptions here and so other object pointers should not have the same issues. So it seems like this case ends up being unique to enums.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/73124/discussion-on-answer-by-shafik-yaghmour-why-must-an-enumerations-size-be-provid). – Taryn Mar 17 '15 at 01:34
7

It's a difference in design goals.

Forward declaring a class creates an incomplete type that can be used opaquely in pointers/references. This is a very useful property.

An incomplete enum type is not that useful. However being able to declare an enum without declaring what constants are inside that enum is useful. The complexity that comes from an incomplete enum type can be avoided by requiring that the size must be specified.

So my best guess is that compiler implementers were kept in mind when this feature was designed, and the committee found that the increased complexity of incomplete enums was not worth the benefits.

orlp
  • 112,504
  • 36
  • 218
  • 315
  • "The complexity that comes from an incomplete enum type can be avoided by requiring that the size must be specified." That may be so (even though I doubt it) but is wholly irrelevant, since it is not a requirement that a size is specified. The requirement is that that the enum type either is scoped or has a specified size, or both. – Cheers and hth. - Alf Mar 13 '15 at 15:08
  • @Cheersandhth.-Alf I'm obviously referring to specifying the size when it can't be inferred. A scoped enum type has a default size of `int`. – orlp Mar 13 '15 at 15:10
  • 1
    What if you want a pointer to an enum? Or reference? That doesn't need any size info at all, just the fact that the name refers to a type. – Yakk - Adam Nevraumont Mar 13 '15 at 15:15
  • 1
    @Yakk My answer explains that. It's not that useful and it complicates the compiler. – orlp Mar 13 '15 at 15:15
  • 1
    @orlp: I fail to see why the standard could not just require e.g. `int` size for forward declared non-scoped non-sized `enum` (i.e. classic `enum`), or indeed why incomplete type should be a problem (it's already handled, and e.g. it doesn't prevent prototyping functions with by-value arguments, there's nothing more to it). I think that means your argument doesn't hold. But then what I wrote wasn't quite right either. – Cheers and hth. - Alf Mar 13 '15 at 15:45
  • @Cheersandhth.-Alf I think that's an oversight, but my argument (the last paragraph) still holds in that case. – orlp Mar 13 '15 at 15:47