Make SDL_Event forward declarable in C++

Hi,

As you probably know it is not possible to forward declare a typedefed
struct or union in C++, although in C is possible. I certainly hope that
SDL is not C++ hostile and you would consider the following patch for inclusion
The patch itself does nothing more than defining the union tag with the same name
of the type(defed) name. If there is more than meets the eye I would like
to be enlightened. Keep in mind that this trick is already used for all the
events structs (SDL_.*Event) and for SDL_KeySym. Hopefully if we extend the
same treatment to unions will not break something.

Thanks in advance for your time.

 .bill

-------------- next part --------------
A non-text attachment was scrubbed…
Name: patch-SDL_Event-forward-declarable.diff
Type: text/x-patch
Size: 293 bytes
Desc: not available
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20051010/3608b9b1/attachment.bin

As you probably know it is not possible to forward declare a typedefed
struct or union in C++, although in C is possible. I certainly hope that
SDL is not C++ hostile and you would consider the following patch for inclusion

-typedef union {
+typedef union SDL_Event {

This header works fine with C++ here without the patch, and as far as I
know, that’s legal code as-is. What compiler doesn’t like it?

–ryan.

Ryan C. Gordon wrote:

As you probably know it is not possible to forward declare a typedefed
struct or union in C++, although in C is possible. I certainly hope that
SDL is not C++ hostile and you would consider the following patch for inclusion

-typedef union {
+typedef union SDL_Event {

This header works fine with C++ here without the patch, and as far as I
know, that’s legal code as-is. What compiler doesn’t like it?

Hi,

I am not saying it is not legal C++. I am just saying it is not possible to
forward declare the union. Consider the following minimal example. It is valid
C but not valid C++. If you argue that forward declaration is not useful at all
then it is a completely another discussion.

---------- cut here -----------
/* this is a forward declaration */
union Foo;

/* and here is the complete type */
typedef union {
int i;
float f;
double d;
} Foo;

int main()
{
return 0;
}
---------- cut here -----------

The error coming from g++ is
fdecl.c:7: error: conflicting declaration 'typedef union Foo Foo’
fdecl.c:1: error: ‘union Foo’ has a previous declaration as ‘union Foo’

If you change it to
typedef union Foo {

} Foo;

It compiles fine under g++ 4.0.1 (Debian sarge)

  .bill

Vassilis Virvilis wrote:

I am not saying it is not legal C++. I am just saying it is not
possible to forward declare the union. Consider the following
minimal example. It is valid C but not valid C++. If you argue
that forward declaration is not useful at all then it is a
completely another discussion.

---------- cut here -----------
/* this is a forward declaration */
union Foo;

You are confusing ‘forward declaration’ with a ‘conflicting declaration’ (or
union declaration with type declaration).
Here ‘union Foo;’ is indeed a forward declaration of a union tagged ‘Foo’.
However, it is not a declaration of a type named ‘Foo’. Such forward
declare would be

typedef union Blah Foo;

so that later you could define ‘union Blah {};’

/* and here is the complete type */
typedef union {
int i;
float f;
double d;
} Foo;

And this would be a type named ‘Foo’ that is defined by an unnamed union.

The reason you may get a different behavior in C++ is because C++ allows to
declare and define full struct/union/class types without a typedef. And
these types can be referred to without their struct/union/class qualifiers.

As applied to SDL code in question, I do not see a problem.

-Alex.

Alex Volkov wrote:

You are confusing

Heh, It won’t be the first or even the last time… :slight_smile:

‘forward declaration’ with a ‘conflicting declaration’ (or

union declaration with type declaration).
Here ‘union Foo;’ is indeed a forward declaration of a union tagged ‘Foo’.
However, it is not a declaration of a type named ‘Foo’.

Agreed.

Such forward declare would be

typedef union Blah Foo;
so that later you could define ‘union Blah {};’

Nope. That won’t work for the case Blah = SDL_Event,
because SDL_Event is a typedefed type and not a tag.
My patch just adds a tag with the same name (SDL_Event)
so I can use the method you described…

And this would be a type named ‘Foo’ that is defined by an unnamed union.

Yes.

The reason you may get a different behavior in C++ is because C++ allows to
declare and define full struct/union/class types without a typedef. And
these types can be referred to without their struct/union/class qualifiers.

Yes! However it is not possible to forward declare a typedefed type without a tag

As applied to SDL code in question, I do not see a problem.

Alex, I don’t see how it is possible for me to do the following:

In a header .h file declare a class that uses SDL_Event * (pointer)
without including the <SDL/SDL_events.h> include file. I want to actually
include the <SDL/SDL_events.h> header later in the .cpp implementation file

One other reason for patch inclusion is that is the norm for other
SDL structs. Consider all the SDL_*Event structures. e.g from SDL cvs…

/* Mouse button event structure /
typedef struct SDL_MouseButtonEvent {
Uint8 type; /
SDL_MOUSEBUTTONDOWN or SDL_MOUSEBUTTONUP /
Uint8 which; /
The mouse device index /
Uint8 button; /
The mouse button index /
Uint8 state; /
SDL_PRESSED or SDL_RELEASED /
Uint16 x, y; /
The X/Y coordinates of the mouse at press time */
} SDL_MouseButtonEvent;

Here both the type and the tag have the same name SDL_MouseButtonEvent. Why not
also the SDL_Event union? It would be uniform and consistent and forward declarable,
and world peace may soon follow…

 .bill