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.
In my projects, I adopted the Namespace-Bound Enumeration technique to deal with
enum
s from legacy and 3rd-party components. Here is an example:forward.h:
enum.h:
foo.h:
foo.cc:
main.cc:
Note that the
foo.h
header does not have to know anything aboutlegacy::evil
. Only the files that use the legacy typelegacy::evil
(here: main.cc) need to includeenum.h
.Seems it can not be forward-declared in GCC!
Interesting discussion here
You can wrap the enum in a struct, adding in some constructors and type conversions, and forward declare the struct instead.
This appears to work: http://ideone.com/TYtP2
I'm adding an up-to-date answer here, given recent developments.
You can forward-declare an enum in C++11, so long as you declare its storage type at the same time. The syntax looks like this:
In fact, if the function never refers to the values of the enumeration, you don't need the complete declaration at all at that point.
This is supported by G++ 4.6 and onwards (
-std=c++0x
or-std=c++11
in more recent versions). Visual C++ 2013 supports this; in earlier versions it has some sort of non-standard support that I haven't figured out yet - I found some suggestion that a simple forward declaration is legal, but YMMV.Just noting that the reason actually is that the size of the enum is not yet known after forward declaration. Well, you use forward declaration of a struct to be able to pass a pointer around or refer to an object from a place that's refered to in the forward declared struct definition itself too.
Forward declaring an enum would not be too useful, because one would wish to be able to pass around the enum by-value. You couldn't even have a pointer to it, because i recently got told some platforms use pointers of different size for char than for int or long. So it all depends on the content of the enum.
The current C++ Standard explicitly disallows doing something like
(in
7.1.5.3/1
). But the next C++ Standard due to next year allows the following, which convinced me the problem actually has to do with the underlying type:It's known as a "opaque" enum declaration. You can even use X by value in the following code. And its enumerators can later be defined in a later redeclaration of the enumeration. See
7.2
in the current working draft.For VC, here's the test about forward declaration and specifying underlying type:
But got the warning for /W4(/W3 not incur this warning)
warning C4480: nonstandard extension used: specifying underlying type for enum 'T'
VC(Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86) looks buggy in the above case:
The above assembly code is extracted from /Fatest.asm directly, not my personal guess. Do you see the mov DWORD PTR[eax], 305419896 ; 12345678H line?
the following code snippet proves it:
the result is: 0x78, 0x56, 0x34, 0x12
the above key instruction becomes:
mov BYTE PTR [eax], 120 ; 00000078H
the final result is: 0x78, 0x1, 0x1, 0x1
Note the value is not being overwritten
So using of the forward-declaration of enum in VC is considered harmful.
BTW, to not surprise, the syntax for declaration of the underlying type is same as its in C#. In pratice I found it's worth to save 3 bytes by specifying the underlying type as char when talk to the embedded system, which is memory limited.