Question

I searched about forward declaration and didn't see any way to make my situation work. So here it is:

1) There is a C-header file, an export interface so to speak for a large multi-component software, that contains an enum typedef

"export.h":

// This is in "C"!
typedef enum _VM_TYPE {...., ...., ...,} VM_TYPE;

2) A part of the code, in C++, uses that export.

"cpp_code.cpp":

// This is in C++
#include "export.h"
#include "cpp_header.hpp"
{ .... using VM_TYPE values to do stuffs....}

"cpp_header.hpp":

// Need to somehow forward declear VM_TYPE here but how?
Struct VM_INFO {
....
VM_TYPE VType; //I need to add this enum to the struct
....
};

So quite obvious, the problem is in cpp_head.hpp, as it doesn't know about the enum.

I tried adding to cpp_header.hpp

typedef enum _VM_TYPE VM_TYPE;

and it'll actually work. So why does THIS work? Because it has C-style syntax?! Anyway, I was told to not do that ("it's C++, not C here") by upper "management".

Is there other way to make this work at all, based on how things are linked currently? They don't want to change/add include files; "enum class" is c++ only, correct? Adding just "enum VM_TYPE" to cpp_header.hpp will get error about redefinition.

Any idea? Thanks.

Was it helpful?

Solution

In the particular situation described in your question, you don't need to forward declare at all. All the files you #include are going to essentially get copy-pasted into a single translation unit before compilation proper begins, and since you #include "export.h" before you #include "cpp_header.hpp", then it'll just work, because by the time the compiler sees the definition of struct VM_INFO, it'll already have seen the definition of enum _VM_TYPE, so you've got no problem. There's basically no difference here between including "export.h" in "cpp_header.hpp", and including them both in "cpp_code.cpp" in that order, since you end up with essentially the same code after preprocessing. So all you have to do here is make sure you get your includes in the correct order.

If you ever wanted to #include "cpp_header.hpp" without including "export.h" in a translation unit where you need to access the members of struct VM_INFO (so that leaving it as an incomplete type isn't an option) then "export.h" is just badly designed, and you should break out the definition of anything you might need separately into a new header. If, as the comments suggest, you absolutely cannot do this and are required to have a suboptimal design, then your next best alternative would be to have two versions of "cpp_header.hpp", one which just repeats the definition of enum _VM_TYPE, and one which does not. You'd #include the first version in any translation unit where you do not also #include "export.h", and #include the second version in any translation unit where you do. Obviously any code duplication of this type is inviting problems in the future.

Also, names beginning with an underscore and a capital letter are always reserved in C, so you really shouldn't use them. If a future version of C ever decides to make use of _VM_TYPE, then you'll be stuck with either using an outdated version of C, or having all this code break.

OTHER TIPS

A enum can not be forward declarations because the compiler needs to know the size of the enum. The underlying a enumerator is compiler specific, but usually a int. Can you just cast the enum as an int?

"I could be and often am wrong"

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top