• Advertisement
Sign in to follow this  

Microsoft's DirectX enums

This topic is 4247 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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;

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.


Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
What you are trying to do makes no logical sense. You want the non-DX part of your project (wrapper or whatever) to have direct access to a DirectX enum. If this part of your project is to allow one to change the buffer formats under DX or OpenGL say, then you really need to abstract the basic concepts into your own format and then convert it to the DirectX one in the DX specific programs.

For example, you could maintain information on the number of bits to use for RGB and optionally A (alpha), a BOOL that indicates whether they want alpha enabled, data specific to the stencil buffer format requested, etc. And you then pass that generic data to your DX specific code that translates it into the DX enum used to create the device. I don't know OpenGL, but would assume it also has specific values used for its buffer formats, and your OpenGL specific code would translate the generic data into the OpenGL specific data.

Trying to achieve data isolation and encapsulation, the way you are doing it, is not a good design or programming practice. You should not keep a platform specific enum in your generic code.

Share this post


Link to post
Share on other sites
Quote:
Original post by DXnut
What you are trying to do makes no logical sense.

In other words, you don't understand.

Quote:
You want the non-DX part of your project (wrapper or whatever) to have direct access to a DirectX enum. If this part of your project is to allow one to change the buffer formats under DX or OpenGL say, then you really need to abstract the basic concepts into your own format and then convert it to the DirectX one in the DX specific programs.

I agree that hiding the API from the settings file would be better future planning if I decide to port or convert my project to something else. But it just doesn't have much to do with the point of this thread. That was just an example. If you're trying to convince me that forward declarations of enums isn't needed, I can shower you with more examples. Just let me know.

Quote:
Trying to achieve data isolation and encapsulation, the way you are doing it, is not a good design or programming practice. You should not keep a platform specific enum in your generic code.

I think you're getting confused. My bad choice to include the DirectX enum in my generic code has nothing to do with my attempt to achieve data isolation. It was just a reason to put isolation to use. A bad example. If I'm wrong, please explain why you believe my isolation and encapsulation is badly designed?

Share this post


Link to post
Share on other sites
Okay, I can see this thread coming to a bit of an "agree to disagree" situation [smile]

As was originally stated by JohnBolton, forward declaring of enums isn't a standard feature. If you want to eliminate the d3dx9.h include you'll probably have to either use a different, but equivalent, enum or you'll have to find a whole different way.

The specification states that front/back buffers can only be one of the following (no matter what hardware appears in the future, this is all you'll have to handle):

A2R10G10B10
A8R8G8B8
X8R8G8B8
A1R5G5B5
X1R5G5B5
R5G6B5


(see "BackBuffer or Display Formats" in D3DFORMAT).

So you could go and create your own custom enum:

enum MyD3DFormat
{
A2R10G10B10 = 31,
A8R8G8B8 = 21,
X8R8G8B8 = 22,
A1R5G5B5 = 24,
X1R5G5B5 = 25,
R5G6B5 = 23
};


Because the values match up, you could expose that enum to your script and simply cast the value straight across to a real D3DFORMAT internally as and when necessary.

Similar approaches can be taken for other subsets of enums.

Quote:
Original post by Kest
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 won't argue with this - I'm also a fan of having "self documenting code" features.

Quote:
Original post by Kest
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);
};
I personally wouldn't want to do this though. Strikes me as a perfect case where typedef is more appropriate. Bare in mind that enum can vary in size between compilers (and even enums - hence the FORCE_DWORD enum you find in the SDK). But I suppose if it works for you then fair enough [smile]

Quote:
Original post by Kest
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.
No, it doesn't cover that specifically (and as JohnBolton commented, its not a standard feature). However it does have several chapters on reducing compile-time dependencies, coupling, class design etc...

Its going off on a tangent, but I'd highly recommend Scott Meyer's and Herb Sutter's texts - they're extremely easy to read and absolutely full with great little tips and tricks. Check out Guru Of The Week for some similar content.


hth
Jack

Share this post


Link to post
Share on other sites
Quote:
Original post by jollyjeffers
Okay, I can see this thread coming to a bit of an "agree to disagree" situation [smile]

That's not very fair. I've already agreed that it wasn't a good idea to expose the settings file to the exact enum type. If we're disagreed about something else, it would be great to know what that was.

Quote:
As was originally stated by JohnBolton, forward declaring of enums isn't a standard feature. If you want to eliminate the d3dx9.h include you'll probably have to either use a different, but equivalent, enum or you'll have to find a whole different way.

It's not that easy for me. I've been using the non-existent feature all over my code. Just as you would forward a class type, I've been forwarding enums. Now I have to decide if I should just get rid of enum names or just accept the fact that my code will only compile with VS.net.

Anyone have any idea if any specific compilers do not support it?

Quote:
So you could go and create your own custom enum:

enum MyD3DFormat
{
A2R10G10B10 = 31,
A8R8G8B8 = 21,
X8R8G8B8 = 22,
A1R5G5B5 = 24,
X1R5G5B5 = 25,
R5G6B5 = 23
};

I don't understand. Wouldn't this be just as bad as using the D3D enum? I mean D3D is in the name. If I have to create my own types, shouldn't I go ahead and make it generic enough to be compatible with other systems?

Quote:
Quote:
Original post by Kest
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);
};
I personally wouldn't want to do this though. Strikes me as a perfect case where typedef is more appropriate.

But then you lose all of the faked type-safety of it. The readability is there, but that's it.

Quote:
Bare in mind that enum can vary in size between compilers (and even enums - hence the FORCE_DWORD enum you find in the SDK).

That is something that I should probably add to mine as well. It would be very nice if the standard would just allow you to specify the size (enum unsigned long Name {}; ?). But instead, programmers are required to add a ball & chain to the bottom of everything. This is why hacks exist. Because the standard isn't up to standard.

Thanks for directing me toward the correct path, even if I may seem like I'm only drunkenly staggering toward it.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement