Microsoft's DirectX enums

Started by
12 comments, last by Kest 17 years, 9 months ago
Microsoft defined their enums using this style: enum _Name { } Name; I'm having trouble forward-declaring these in header files while using the normal names rather than the underscored names. For example:

// SomeHeader.h

// Forward the enum type
enum D3DFORMAT;

// Define setup structure
struct DisplayDataSetup
{
    ...
    D3DFORMAT    CurrentFormat;
    ...
};
I get a "redefinition; different basic types" error. I can't seem to use the friendly enum names, and instead have to use the underscore versions. Is there a reason they did this? Or am I just missing something very simple and obvious? Thanks edit: Actually, after looking it over again, it's possible that they are doing this instead, but my same problems remain:

enum _Name
{

};
typedef enum _Name Name;
edit 2: Oops, had D3DFormat instead of D3DFORMAT. [Edited by - Kest on July 7, 2006 8:18:03 PM]
Advertisement
Why are you doing a "forward declare" for a DX enum? If you just include the d3d9.h file, it will include the file that that enum is in. If for some strange reason you are including that file AFTER you define some structs that use those enums, then it may work. I have never seen this done before with an enum tho. Usually forward definitions are used for classes, when you want one class to include another class that is not defined yet.
--------------------------Most of what I know came from Frank D. Luna's DirectX books
While it would be nice to be able to forward-declare enums, that feature is not part of the standard. That might be your problem.

In general, when a struct or class is declared like this:
    typedef struct class_name    {        ...    } typedef_name; 
You must forward declare it and use it like this:
    struct class_name;    void foo( class_name * bar ); 
You basically cannot use typedef_name in the header file. Well, you might be able to duplicate the typedef -- I've never tried. It is a pain in the butt when people use different names for class_name and typedef_name. If it were declared like this, there would be no problem:
    typedef struct class_name    {        ...    } class_name; 
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Quote:Original post by DXnut
Why are you doing a "forward declare" for a DX enum? If you just include the d3d9.h file, it will include the file that that enum is in.

Because I don't want to include d3d9.h in every file that sees the enum variable. It's just an int. My project takes long enough to compile as it is.

Quote:If for some strange reason you are including that file AFTER you define some structs that use those enums, then it may work.

It's not strange to want to hide d3d from everything I can.

Quote:I have never seen this done before with an enum tho. Usually forward definitions are used for classes, when you want one class to include another class that is not defined yet.

What's the difference? You can't have a class that includes an enum variable that is not defined yet? What if the enum values are grouped with the forwarded class because it is part of the forwarded class functionality?
class OtherObject;enum OtherObjectType;class MyObject{    OtherObject   *Thingo;    OtherObjectType ThingoType;};

Following your suggestion would expose everything that sees MyObject to OtherObject, even though there is no need. I would sooner declare ThingoType as an int and just cast it later. But that pretty much destroys the entire purpose of using enums.

Quote:Original post by JohnBolton
While it would be nice to be able to forward-declare enums, that feature is not part of the standard. That might be your problem.

Ack! I had no idea. Why isn't it part of the standard? I've been doing it for a while now, so it's definitely supported by Visual Studio. But as you pointed out, I just can't forward it with the typedef name.

Thanks for the info
Sorry, I am relatively new to C++. I just assumed it was normal to include the header files you need at the top of one's cpp files. So, you find that your compilation goes faster if you forward declare an enum in a .cpp file, use it somewhere below that, and then somewhere below that include the d3d9.h file?

Don't you have to include it somewhere anyway so the forward declare will work? How would that make it faster?

Thanks.


--------------------------Most of what I know came from Frank D. Luna's DirectX books
Quote:Original post by DXnut
Don't you have to include it somewhere anyway so the forward declare will work? How would that make it faster?

You could create a D3D wrapper object, and that object may pass around D3D format variables. Now if anything is exposed to this class, it won't be exposed to D3D, even though you may be declaring D3D pointers and enum values in the header.

Even if D3D is the only graphics API you use, this wrapper class could have functions like DrawRectangle and DrawLine. So many parts of your code might want to use those. With the lack of including the header, none of these parts of code would ever be exposed to Direct3D. Meaning every source file that wants to draw something but doesn't include D3D will compile a lot faster.

It's not just about compile time, though. I want to forward declare enums for exactly the same reasons anyone would want to forward declare a class or structure.
Have you looked into precompiled headers?

I'd personally be very wary of messing around with my application design to improve compile times. That strikes me as taking it too far.

If you're doing it to reduce coupling then you might want to take a step back and ask yourself why the client code needs access to such primitive/low-level D3D implementation details. Its a bit questionable, but remember that most (if not all) D3D Enum's are DWORD padded - so you could (and I've done this before) replace D3DFORMAT with DWORD and just do a static_cast<D3DFORMAT>( m_dwFormat ); type operation internally.

Finally, you might want to consider the pimpl idiom - I was reading about it last night in Herb Sutter's Exceptional C++ book. I'm sure there are other resources, but his description in particular seemed to cover what you want.

Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Quote:Original post by jollyjeffers
I'd personally be very wary of messing around with my application design to improve compile times. That strikes me as taking it too far.

I would hardly consider include reduction a mess with design.

Quote:If you're doing it to reduce coupling then you might want to take a step back and ask yourself why the client code needs access to such primitive/low-level D3D implementation details.

The enum value is visible, but visibility doesn't mean accessible. It's an engine setup structure. It allows my start up system to give scripting access to a few files, which allow these files to control the way the APIs are set up. Nothing but primitive types exist in it. I had the format declared as an int, but then thought it might be a bit more safe to use the enum type.

Quote:Its a bit questionable, but remember that most (if not all) D3D Enum's are DWORD padded - so you could (and I've done this before) replace D3DFORMAT with DWORD and just do a static_cast<D3DFORMAT>( m_dwFormat ); type operation internally.

Like I said before, I would rather forward the enum and use the actual underscored names.
Quote:Original post by Kest
Quote:Original post by jollyjeffers
I'd personally be very wary of messing around with my application design to improve compile times. That strikes me as taking it too far.

I would hardly consider include reduction a mess with design.
Agreed, but given a particular design it might not be possible to reduce the number of includes without changing the design. That was my point - changing the design to suit reduced compile time (etc..).

Quote:Original post by Kest
Quote:If you're doing it to reduce coupling then you might want to take a step back and ask yourself why the client code needs access to such primitive/low-level D3D implementation details.

The enum value is visible, but visibility doesn't mean accessible.
That sounds contradictory to me. In a struct, visible is accessible. In a class, visible is public is accessible, private and protected can use alternative means to hide implementation (see my pimpl reference).

Quote:Original post by Kest
It's an engine setup structure. It allows my start up system to give scripting access to a few files, which allow these files to control the way the APIs are set up.
My point still stands - take a step back; do they really, and I mean REALLY, need access to implementation specifics? I can think of a number of ways I'd expose my API to a scripting language without revealing the internal/implementation details.

For setup structure the entire D3DFORMAT listing is never valid - a subset are valid for front/back buffers, another subset for the DST. All of which could be abstracted out to a relatively simple custom enum and translated accordingly. You can even do a direct cast from custom enum to D3DFORMAT if you set it up correctly [wink]

Quote:Original post by Kest
I had the format declared as an int, but then thought it might be a bit more safe to use the enum type.
This is the same as what I said regarding casting from a DWORD, but you responded with:
Quote:I would rather forward the enum and use the actual underscored names.
So I'm confused [smile]

As I hinted at before, I'd recommend grabbing a copy of Exceptional C++ - it's very cheap for a tech book and it covers some of the points you're raising.

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Quote:Original post by jollyjeffers
Agreed, but given a particular design it might not be possible to reduce the number of includes without changing the design. That was my point - changing the design to suit reduced compile time (etc..).

Well, I always try to keep the number of non allocated objects in classes as low as I can. It doesn't change the design, but it sometimes requires an allocation in the constructor. Pointer types don't need to be declared at all as long as the object is not exposed to it's functionality. And using this design keeps the visibility of other types as low as possible.

Quote:My point still stands - take a step back; do they really, and I mean REALLY, need access to implementation specifics? I can think of a number of ways I'd expose my API to a scripting language without revealing the internal/implementation details.

Well, no, they don't need absolute access in the script startup file. But doing so allows access outside of code to change Direct3D settings to values that aren't even available now. It's also very helpful if something doesn't work well with certain hardware. They can tweak values to anything, including values that I wouldn't even consider being needed. R7G9B8A8? Who knows. Way beside the point, though.

Quote:
Quote:Original post by Kest
I had the format declared as an int, but then thought it might be a bit more safe to use the enum type.
This is the same as what I said regarding casting from a DWORD, but you responded with:
Quote:I would rather forward the enum and use the actual underscored names.
So I'm confused [smile]

I'm saying that my original setup worked exactly like you're suggesting. But I'm pretty fond of enum types. I love types being declared with enum names, because it reduces the number of 'unknown' bland int types. You might even say I look at int or DWORD like a void pointer and enum named types like real type pointers.

void *myrug; // what does this point to?
rug *myrug; // Ahh, this is a rug object

int myrug; // huh?
RugType myrug; // ahh. Very obvious what this is. And the compiler will slap you around if you try to send an int in it's place. But if you cast ints to these, you've completely destroyed the point.

I've even declared enums for situatuons like this:
enum Val_RaceID { NOTHING_HERE; }
class Race
{
Val_RaceID FindRace(const char *name);
const char* GetRaceName(Val_RaceID id);
};

The only casting from int to RaceID takes place inside of the race class.

I've thought about other ways to accomplish this.
typedef int RaceID; won't work. It'll still let you send an int to the variable.
struct Val_RaceID { int RealID; }; is really messy.

Quote:As I hinted at before, I'd recommend grabbing a copy of Exceptional C++ - it's very cheap for a tech book and it covers some of the points you're raising.

It explains how to forward declare enums? That's what I need.

My character class requires suit objects, item inventories, animations, animation maps, AI control structures, input control structures, etc. I don't want to expose everything that sees my character to all of these internal object types. But what if I need to have an enum AI_CurrentTask variable declared in the character class? Or what if one of these enums types need sent to a character function? Even if it's a private function, it still needs forwarded to everything that knows my characters exist. I could declare as long or int, and then cast, but then I might as well not even name my enum.

This topic is closed to new replies.

Advertisement