CapelliC
CapelliC

Reputation: 60034

enums declaration in struct

Horde3d claims a C 'style' interface available. But I'm unable to include the headers compiling a C source, because of these errors:

..../../horde3d/SDK_1.0.0_Beta5/Horde3D/Bindings/C++/Horde3D.h:127: error: nested redefinition of ‘enum List’

due to these declarations:

....

struct H3DOptions
{
    /* ... */
    enum List
    {
        MaxLogLevel = 1,
        MaxNumMessages,
        TrilinearFiltering,
        ....
    };
...
};

struct H3DStats
{
    /* ... */
    enum List
    {
        TriCount = 100,
        BatchCount,
        LightPassCount,
        ...
    };
};

....

Being Horde3d really developed in C++, the identifier List get qualified by enclosing struct. This seem not available in C. Does exists some workaround, apart rewriting the headers?

Upvotes: 2

Views: 595

Answers (3)

CapelliC
CapelliC

Reputation: 60034

I (almost) found the solution I was looking for: a set of macros that placed before the include allows interfacing Horde3D in C.

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#include <GL/freeglut.h>

#define TOKPASTE1(x, y) x ## y
#define TOKPASTE2(x, y) TOKPASTE1(x, y)

/* List is shared between many structs
 */
#define List TOKPASTE2(List_, __LINE__)

/* these symbols are duplicated: their functionality is compromised
 */
#define Code TOKPASTE2(Code_, __LINE__)
#define SamplerElem TOKPASTE2(SamplerElem_, __LINE__)
#define UniformElem TOKPASTE2(UniformElem_, __LINE__)
#define SampNameStr TOKPASTE2(SampNameStr_, __LINE__)
#define UnifNameStr TOKPASTE2(UnifNameStr_, __LINE__)
#define Undefined   TOKPASTE2(Undefined_,   __LINE__)
#define MatResI     TOKPASTE2(MatResI_,     __LINE__)

#include <Horde3D.h>
#include <Horde3DUtils.h>

/* disambiguate C client code:
   let the compiler signal eventual usage of compromised symbols
 */
#undef List
#undef Code
#undef SamplerElem
#undef UniformElem
#undef SampNameStr
#undef UnifNameStr
#undef Undefined
#undef MatResI

edit

As Christoph pointed out, it's use of non C tokens that inhibits a full solution. These macros above leave just 3 errors due to H3DOptions::List and H3DStats::List usage. I've then edited the Horde3D.h, and added

#define H3DStats__List int
#define H3DOptions__List int

to the macros above. Compiling in C++ with now would require

#define H3DStats__List H3DStats::List
#define H3DOptions__List H3DOptions::List

Upvotes: 1

Bo Persson
Bo Persson

Reputation: 92381

It was done on purpose. Appendix C of the C++ standard explains:

Change: A struct is a scope in C++, not in C
Rationale: Class scope is crucial to C++, and a struct is a class.
Effect on original feature: Change to semantics of well-defined feature.
Difficulty of converting: Semantic transformation.
How widely used: C programs use struct extremely frequently, but the change is only noticeable when struct, enumeration, or enumerator names are referred to outside the struct. The latter is probably rare.

Obviously the committee only considered how valid C code would work as C++, not if C++ code using the new features would still be valid C.

Upvotes: 3

ouah
ouah

Reputation: 145899

In C, in a single translation unit all enum tag names live in the same name space, you cannot reuse them twice. You have to change your second enum tag if you want both of them to coexist.

Upvotes: 2

Related Questions