I'm trying to do something like the following:
enum E;
void Foo(E e);
enum E {A, B, C};
which the compiler rejects. I've had a quick look on Google and the consensus seems to be "you can't do it", but I can't understand why. Can anyone explain?
Clarification 2: I'm doing this as I have private methods in a class that take said enum, and I do not want the enum's values exposed - so, for example, I do not want anyone to know that E is defined as
enum E {
FUNCTIONALITY_NORMAL, FUNCTIONALITY_RESTRICTED, FUNCTIONALITY_FOR_PROJECT_X
}
as project X is not something I want my users to know about.
So, I wanted to forward declare the enum so I could put the private methods in the header file, declare the enum internally in the cpp, and distribute the built library file and header to people.
As for the compiler - it's GCC.
I'd do it this way:
[in the public header]
[in the internal header]
By adding FORCE_32BIT we ensure that Econtent compiles to a long, so it's interchangeable with E.
Forward declaring things in C++ is very useful because it dramatically speeds up compilation time. You can forward declare several things in C++ including:
struct
,class
,function
, etc...But can you forward declare an
enum
in C++?No you can't.
But why not allow it? If it were allowed you could define your
enum
type in your header file, and yourenum
values in your source file. Sounds like it should be allowed right?Wrong.
In C++ there is no default type for
enum
like there is in C# (int). In C++ yourenum
type will be determined by the compiler to be any type that will fit the range of values you have for yourenum
.What does that mean?
It means that your
enum
's underlying type cannot be fully determined until you have all of the values of theenum
defined. Which mans you cannot separate the declaration and definition of yourenum
. And therefore you cannot forward declare anenum
in C++.The ISO C++ standard S7.2.5:
You can determine the size of an enumerated type in C++ by using the
sizeof
operator. The size of the enumerated type is the size of its underlying type. In this way you can guess which type your compiler is using for yourenum
.What if you specify the type of your
enum
explicitly like this:Can you then forward declare your
enum
?No. But why not?
Specifying the type of an
enum
is not actually part of the current C++ standard. It is a VC++ extension. It will be part of C++0x though.Source
Because the enum can be an integral size of varying size (the compiler decides which size a given enum has), the pointer to the enum can also have varying size, since it's an integral type (chars have pointers of a different size on some platforms for instance).
So the compiler can't even let you forward-declare the enum and user a pointer to it, because even there, it needs the size of the enum.
You define an enumeration to restrict the possible values of elements of the type to a limited set. This restriction is to be enforced at compile time.
When forward declaring the fact that you will use a 'limited set' later on doesn't add any value: subsequent code needs to know the possible values in order to benefit from it.
Although the compiler is concerned about the size of the enumerated type, the intent of the enumeration gets lost when you forward declare it.
There's some dissent since this got bumped (sort of), so here's some relevant bits from the standard. Research shows that the standard doesn't really define forward declaration, nor does it explicitly state that enums can or can't be forward declared.
First, from dcl.enum, section 7.2:
So the underlying type of an enum is implementation-defined, with one minor restriction.
Next we flip to the section on "incomplete types" (3.9), which is about as close as we come to any standard on forward declarations:
So there, the standard pretty much laid out the types that can be forward declared. Enum wasn't there, so compiler authors generally regard forward declaring as disallowed by the standard due to the variable size of its underlying type.
It makes sense, too. Enums are usually referenced in by-value situations, and the compiler would indeed need to know the storage size in those situations. Since the storage size is implementation defined, many compilers may just choose to use 32 bit values for the underlying type of every enum, at which point it becomes possible to forward declare them. An interesting experiment might be to try forward declaring an enum in visual studio, then forcing it to use an underlying type greater than sizeof(int) as explained above to see what happens.
[My answer is wrong, but I've left it here because the comments are useful].
Forward declaring enums is non-standard, because pointers to different enum types are not guaranteed to be the same size. The compiler may need to see the definition to know what size pointers can be used with this type.
In practice, at least on all the popular compilers, pointers to enums are a consistent size. Forward declaration of enums is provided as a language extension by Visual C++, for example.