Forward declarations and typedef

P

Paul N

I'm getting in knots trying to declare a header, and it's to do with a
typedef. First, an example. If I do this:

struct realname;

void fun(realname& val);

struct realname { int val; };

then this compiles fine. (It doesn't link, of course.) If the compiler
knows that realname is a struct it is perfectly happy to let me
declare a function taking a reference to one, even if it doesn't yet
know what's in the struct.

But if I do this:

struct fakename;

void fun(fakename& val);

struct realname { int val; };

typedef realname fakename;

it doesn't compile. Am I just getting the syntax wrong or is it
fundamentally impossible?

My actual problem is that I want to have a header which declares some
functions that take a reference to a OPENFILENAME struct. OPENFILENAME
is defined in non-standard system header <commdlg.h>, but it's defined
via two typedefs. Is there any way I can create a header containing
lines like:

void fileinit(OPENFILENAME& fileopenstruct, HWND owner);

without needing to always include commdlg.h before my own header?

Many thanks.
Paul.
 
J

Juha Nieminen

Paul N said:
But if I do this:

struct fakename;

void fun(fakename& val);

struct realname { int val; };

typedef realname fakename;

it doesn't compile.

typedef doesn't declare a strong type, so it cannot be used like that.

There's no direct way of doing that in the current standard, but in
some cases you can "abuse" inheritance to make a strong type alias.
In other words:

struct fakename: public realname {};

Whether this is good design is another question.
 
H

Helge Kruse

But if I do this:

struct fakename;

void fun(fakename& val);

struct realname { int val; };

typedef realname fakename;

it doesn't compile. Am I just getting the syntax wrong or is it
fundamentally impossible?

Try this one:

struct realname;

typedef realname fakename;

void fun(fakename& val);

struct realname { int val; };

You tell the compiler that you will sometimes define the realname structure.
And you tell him, that there is a fakename that will be used as type for
reference or pointer parameter. After using it you can define the realname
struct.

This let your postpone the definition of the struct realname as long as you
don't need access to any member.


Helge
 
B

Bart van Ingen Schenau

it doesn't compile. Am I just getting the syntax wrong or is it
fundamentally impossible?

It is fundamentally impossible to create a forward declaration for a
typedef.
A typedef just tells the compiler that you want to use an alternative
name for another type. Just saying "this will later be defines as an
alias" does not give the compiler enough information to use the alias
in any way.
My actual problem is that I want to have a header which declares some
functions that take a reference to a OPENFILENAME struct. OPENFILENAME
is defined in non-standard system header <commdlg.h>, but it's defined
via two typedefs. Is there any way I can create a header containing
lines like:

void fileinit(OPENFILENAME& fileopenstruct, HWND owner);

without needing to always include commdlg.h before my own header?
No.


Many thanks.
Paul.

Bart v Ingen Schenau
 
P

Paul N

Thanks to all three of you who replied. Unfortunately, it seems I
can't do what I want, but you've given me some food for thought!

It is fundamentally impossible to create a forward declaration for a
typedef.
A typedef just tells the compiler that you want to use an alternative
name for another type. Just saying "this will later be defines as an
alias" does not give the compiler enough information to use the alias
in any way.

This seems a shame. It can handle references to structs where it knows
nothing about the struct, so it would seem possible for it to handle
aliases that it knows will be aliases of some sort of struct... but
still, the language doesn't do everything that it ought to be possible
for it to do.

Pity. But thanks for your help.
 
J

James Kanze

Thanks to all three of you who replied. Unfortunately, it seems I
can't do what I want, but you've given me some food for thought!
This seems a shame. It can handle references to structs where
it knows nothing about the struct, so it would seem possible
for it to handle aliases that it knows will be aliases of some
sort of struct... but still, the language doesn't do
everything that it ought to be possible for it to do.

In the case of references to structs, it does know that it is
dealing with a struct, and it knows the name of the struct.
There are two reasons why this doesn't work with typedef's:

-- Historically, not all pointers have the same size and
representation. I've actually worked on machines where
a char* was bigger than an int*. (The fact that you can
create pointers and references to incomplete class types
indirectly means that all pointers to class types must have
the same size and representation.) This is the reason why
the restriction was introduced in C, and it is still
somewhat of a motivation, even if I don't know of any
machines where char* and int* have different sizes today.

-- In C++, arguments can be overloaded, and the argument type
is passed through to the linker, so that it can choose the
correct function to bind. (This is typically done by
mangling the function name, but better techniques are
possible.) This means that the compiler must be able to
name the type. And since a typedef doesn't introduce a new
name, it needs to be able to name what the typedef refers
to. Which makes forward declarations of typedef pretty much
impossible. This argument is still very valid today, since
it affects all existing implementations.
 
H

Helge Kruse

Paul N said:
Thanks to all three of you who replied. Unfortunately, it seems I
can't do what I want, but you've given me some food for thought! ....

Pity. But thanks for your help.
While you can't create a forward declaration for typedef you can create a
typedef to a forward dcelared type. I though this should do it as suggested
in my post. Shouldn't this be sufficient?

Helge
 
P

Paul N

While you can't create a forward declaration for typedef you can create a
typedef to a forward dcelared type. I though this should do it as suggested
in my post. Shouldn't this be sufficient?

What I'm trying to do is create a header, including the declaration

void fileinit(OPENFILENAME& fileopenstruct, HWND owner);

which can be included without requiring the header <commdlg.h>.

As far as I can tell, the following ought to work:

struct tagOFNW;
typedef struct tagOFNW OPENFILENAMEW;
typedef OPENFILENAMEW OPENFILENAME;
void fileinit(OPENFILENAME& fileopenstruct, HWND owner);

and this is what you are recommending, is it not?

The snag is with this is that it relies an awful lot on details that
ought to be hidden away in <commdlg.h>. I was hoping for something
that simply said that OPENFILENAME referred (indirectly) to some sort
of structure - and it seems this is what I can't have. James Kanze has
offered a possible explanation for this, regarding name mangling to
allow overloading.

Sorry to be so negative.

Paul.
 
Ö

Öö Tiib

What I'm trying to do is create a header, including the declaration

void fileinit(OPENFILENAME& fileopenstruct, HWND owner);

which can be included without requiring the header <commdlg.h>.

As far as I can tell, the following ought to work:

struct tagOFNW;
typedef struct tagOFNW OPENFILENAMEW;
typedef OPENFILENAMEW OPENFILENAME;
void fileinit(OPENFILENAME& fileopenstruct, HWND owner);

and this is what you are recommending, is it not?

The snag is with this is that it relies an awful lot on details that
ought to be hidden away in <commdlg.h>. I was hoping for something
that simply said that OPENFILENAME referred (indirectly) to some sort
of structure - and it seems this is what I can't have. James Kanze has
offered a possible explanation for this, regarding name mangling to
allow overloading.

Sorry to be so negative.

Options are:
1) to not put things that depend on <windows.h> and its pals into
interfaces (header files).
2) have <windows.h> and comrades always included in all translation
units (cpp files).
3) include that <commdlg.h> or whatever else you need in your header.
4) prepare some "platform.h" that defines the subset of <windows.h>
and brothers (existence of what you have to expose for some strange
reasons) and include that "platform.h"

So you still have plenty of options, don't be negative.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,697
Latest member
AugustNabo

Latest Threads

Top