Topic: Why no forward declare for typedefs?


Author: brangdon@cix.co.uk (Dave Harris)
Date: Wed, 2 Oct 2002 17:28:17 +0000 (UTC)
Raw View
richard@ex-parrot.com (Richard Smith) wrote (abridged):
> So what can you do with a forward-declared enum that is a 'partial
> type' like this?  The only things I can think of is prototype a
> function that takes and/or returns one (although not calling it,
> because that would require knowing the size of either the enum or of a
> pointer to it), and instantiate some templates with the type as a
> template argument. Neither of these strike me as particularly useful.

Being able to declare functions that take or return the enum is useful for
dependency management. It means the header that declares the function does
not have to #include the header that defines the enum.

The difference is not that great if the enum is the only thing that header
contains. However, code is often more readable if the enum is kept near
the routines which give it meaning, so the header will often contain other
classes and the #includes they need. Anything which cuts down the
exponential growth of #include files is welcome.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Russell Kuyper Jr.")
Date: Fri, 27 Sep 2002 11:50:16 +0000 (UTC)
Raw View
James Kanze wrote:
....
> without really asking too many questions.  The fact that C++ doesn't
> have layout-compatible types (I don't think) may mean that the trick

C++ does have layout-compatible typse. See 3.9p 11, 7.2p7, 9.2p14-16.
It's C which doesn't have the concept of "layout-compatible types". The
term the C standard uses is "compatible types". There are some subtle
differences between the two definitions, but they're pretty close.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: news_comp.std.c++_expires-2002-10-01@nmhq.net (Niklas Matthies)
Date: Fri, 27 Sep 2002 16:34:30 +0000 (UTC)
Raw View
On Thu, 26 Sep 2002 23:03:59 +0000 (UTC), "James Russell Kuyper Jr." <kuyper@wizard.net> wrote:
>  Niklas Matthies wrote:
> >
> > On Wed, 25 Sep 2002 23:25:18 +0000 (UTC), "James Russell Kuyper Jr." <kuyper@wizard.net> wrote:
> > >  Niklas Matthies wrote:
> > >  ....
> > > > The restriction seems to be that for those implementations where the
> > > > sizes of char* and int* are different, enums would have to be at least
>
>  ^^^^^^^^^^^^^^^^^^^
> > > > of size int even if their range would fit into a char. Most likely
>        ^^^^^^^^^^^
> > > > that's already the case anyway.
> > >
> > >  I don't see how the size of pointers and the size of enumeration types
> > >  are connected. Could you explain?
> >
> > The point was made that there are implementations where the sizes of
> > char* and int* differ (presumably for the reason that the architecture's
> > "natural" pointers are word pointers, which requires byte pointers to
> > carry additional information), hence the sizes of pointers to char-sized
> > and to int-sized enums would differ as well.
>
>  Yes, but I don't see how that ends up prohibiting char-sized enums.
>  That's the connection that escapes me.

You are right, a different solution would be to make all pointers-to-enum
pointer-to-char-sized even though int-sized enums would be happy with
smaller pointer-to-int-sized pointers.

-- Niklas Matthies
--
Avril Lavigne in bear pajama NOW!

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Russell Kuyper Jr.")
Date: Sat, 28 Sep 2002 21:46:54 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> On Thu, 26 Sep 2002 23:03:59 +0000 (UTC), "James Russell Kuyper Jr." <kuyper@wizard.net> wrote:
> >  Niklas Matthies wrote:
> > >
> > > On Wed, 25 Sep 2002 23:25:18 +0000 (UTC), "James Russell Kuyper Jr." <kuyper@wizard.net> wrote:
> > > >  Niklas Matthies wrote:
> > > >  ....
> > > > > The restriction seems to be that for those implementations where the
> > > > > sizes of char* and int* are different, enums would have to be at least
> >
> >  ^^^^^^^^^^^^^^^^^^^
> > > > > of size int even if their range would fit into a char. Most likely
> >        ^^^^^^^^^^^
> > > > > that's already the case anyway.
> > > >
> > > >  I don't see how the size of pointers and the size of enumeration types
> > > >  are connected. Could you explain?
> > >
> > > The point was made that there are implementations where the sizes of
> > > char* and int* differ (presumably for the reason that the architecture's
> > > "natural" pointers are word pointers, which requires byte pointers to
> > > carry additional information), hence the sizes of pointers to char-sized
> > > and to int-sized enums would differ as well.
> >
> >  Yes, but I don't see how that ends up prohibiting char-sized enums.
> >  That's the connection that escapes me.
>
> You are right, a different solution would be to make all pointers-to-enum
> pointer-to-char-sized even though int-sized enums would be happy with
> smaller pointer-to-int-sized pointers.

Or, as an even better solution, pointer-to-char-sized enum would have
the same size as char*, while pointer-to-int-sized enums would have the
same size as int*. To the best of my knowledge, there's nothing in the
standard that requires all enums to have pointers of the same size.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: andys@evo6.com (Andy Sawyer)
Date: Mon, 30 Sep 2002 17:10:50 +0000 (UTC)
Raw View
[JK=kuyper@wizard.net ("James Russell Kuyper Jr.") writes:

[NM=Niklas Matthies]

NM> You are right, a different solution would be to make all pointers-to-enum
NM> pointer-to-char-sized even though int-sized enums would be happy with
NM> smaller pointer-to-int-sized pointers.


JK> Or, as an even better solution, pointer-to-char-sized enum would have
JK> the same size as char*, while pointer-to-int-sized enums would have the
JK> same size as int*. To the best of my knowledge, there's nothing in the
JK> standard that requires all enums to have pointers of the same size.

You're absolutely right - except then you end up in the situation
we're in now, where you can't use a pointer to a a forward-declated
enum. Which was, I think, rather the point...


--
"Light thinks it travels faster than anything but it is wrong. No matter
 how fast light travels it finds the darkness has always got there first,
 and is waiting for it."                  -- Terry Pratchett, Reaper Man

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: news_comp.std.c++_expires-2002-10-01@nmhq.net (Niklas Matthies)
Date: Mon, 30 Sep 2002 17:11:27 +0000 (UTC)
Raw View
On Sat, 28 Sep 2002 21:46:54 +0000 (UTC), "James Russell Kuyper Jr." <kuyper@wizard.net> wrote:
>  Niklas Matthies wrote:
> > On Thu, 26 Sep 2002 23:03:59 +0000 (UTC), "James Russell Kuyper Jr." <kuyper@wizard.net> wrote:
> > >  Niklas Matthies wrote:
> > > > On Wed, 25 Sep 2002 23:25:18 +0000 (UTC), "James Russell Kuyper Jr." <kuyper@wizard.net> wrote:
[...]
> > > > >  I don't see how the size of pointers and the size of
> > > > >  enumeration types are connected. Could you explain?
> > > >
> > > > The point was made that there are implementations where the
> > > > sizes of char* and int* differ (presumably for the reason that
> > > > the architecture's "natural" pointers are word pointers, which
> > > > requires byte pointers to carry additional information), hence
> > > > the sizes of pointers to char-sized and to int-sized enums would
> > > > differ as well.
> > >
> > >  Yes, but I don't see how that ends up prohibiting char-sized enums.
> > >  That's the connection that escapes me.
> >
> > You are right, a different solution would be to make all pointers-to-enum
> > pointer-to-char-sized even though int-sized enums would be happy with
> > smaller pointer-to-int-sized pointers.
>
>  Or, as an even better solution, pointer-to-char-sized enum would have
>  the same size as char*, while pointer-to-int-sized enums would have the
>  same size as int*.

The context of this discussion was using pointers to forward-declared
enums in e.g. function declarations, where the compiler would need to
know the size of the pointer-to-enum without knowing the size of the
enum, hence all pointers-to-enum would need to have the same size
regardless of the size of the enum pointed to.

>  To the best of my knowledge, there's nothing in the
>  standard that requires all enums to have pointers of the same size.

Right, but the ability to forward-declare enums would most likely imply
such a requirement.

-- Niklas Matthies
--
Save Farscape - get informed and involved: http://farscape.wdsection.com/
Together, we can get Farscape back on air. Crackers *do* matter.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 30 Sep 2002 23:01:31 +0000 (UTC)
Raw View
news_comp.std.c++_expires-2002-10-01@nmhq.net (Niklas Matthies) wrote
(abridged):
> The point was made that there are implementations where the sizes of
> char* and int* differ (presumably for the reason that the architecture's
> "natural" pointers are word pointers, which requires byte pointers to
> carry additional information), hence the sizes of pointers to char-sized
> and to int-sized enums would differ as well.

So if we go this route, an implementation where sizeof(char *) > sizeof
(int *) has 2 options:

(1) All pointers to enums must be sizeof(char *).
(2) All enums must be at least sizeof(int).

The first option has the advantage that pointers to enums are rare. I
suspect large enums are quite rare too. Few programs would pay any
additional cost.

In practice, I would expect the second option to be better. When the
hardware is so hostile to byte addressing it's best to avoid it. Even on
the 80x86, which is not hostile, some implementations choose to use
sizeof(int) for small enums.

At the standards level, we have a 3rd option:

(3) Pointers to forward-declared enums are partial types.

This makes it harder to use pointers to forward-declared enums, but as
we've already remarked, such things are rarely used so it doesn't matter
much. Indeed, with the current standard they cannot be used at all because
there are no forward-declared enums for them to point to.

In practice I expect implementations on which sizeof(char *) == sizeof(int
*) would offer an extension to the standard where-by pointers to forward
declared enums were complete types.

I think I prefer the 3rd option, which seems all gain with no cost, but I
would see any of them as an improvement over the current language. I use
enums frequently, and I'd love to be able to forward-declare them.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Russell Kuyper Jr.")
Date: Wed, 25 Sep 2002 23:25:18 +0000 (UTC)
Raw View
Niklas Matthies wrote:
....
> The restriction seems to be that for those implementations where the
> sizes of char* and int* are different, enums would have to be at least
> of size int even if their range would fit into a char. Most likely
> that's already the case anyway.

I don't see how the size of pointers and the size of enumeration types
are connected. Could you explain?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 26 Sep 2002 12:46:19 +0000 (UTC)
Raw View
> > I believe that pointers to data are allowed to be different size than
> > a pointer to a function.
>
> Pointers to data are allowed to vary even between different types.
> A pointer to void will be the same size as pointer to char.  They have
> to be able to hold the converted value of any other object pointer.

You're right. I tend to forget about this, because it's been so long
since I used a platform where this could have happened -- and when I
did, I used neither C nor C++.

In practice, though, no data pointer is going to be larger than a
void*. That's because it has to be possible to convert any pointer
to void* and then back again without losing information.


> I don't have a clue what a pointer-to-free is.

Okay, I didn't say it very well, but I think the context made it clear:
: a pointer-to-member is almost always a different size than a
: pointer-to-free.
I meant, "a pointer to a non-member variable or function."

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 26 Sep 2002 16:26:51 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote
> >> You see the problem is that different
> >> types have different size pointers (and quite possibly different ways of
> >> representing a reference),

> Allan W <allan_w@my-dejanews.com> writes
> >I believe that pointers to data are allowed to be different size than
> >a pointer to a function. Furthermore, a pointer-to-member is almost
> >always a different size than a pointer-to-free. And, if I remember
> >correctly, a pointer-to-void could potentially be different than all
> >of these.
> >
> >That's a far cry from having a different size for every possible pointer
> >type!
>
> I did not say that.

Didn't mean to imply that you did. I'm just saying: it's not as bad
as it could have been.

> iosfwd is a red herring. The need for it is related to the fact that
> those types are provided by templates and so cannot be forward declared
> by the user.

The need for iosfwd is related to the fact that those types are
typedefs (in this case, for template instantiations). If the library
had been designed so that iosfwd was an empty specialization, things
would have been different (but also less efficient).

But step back. The real problem isn't that std::istream isn't a class.
The real problem is, we want to have the class exist (so that we can
refer to it in limited ways) without having to drag in <iostream>.
The usual answer, forward declarations, isn't possible in this case.
Unfortunately, the <iostream> classes are not alone in this distinction,
as I suggested with my hypothetical VendorX library. Didn't it seem
at least vaguely familiar?

> The restriction that would be needed to allow forward declaration of
> enum types seems out of all proportion to the minuscule places where
> such would be of any use. Forward declaration allows pointers and
> references but not the type itself. As I have never come across using
> either for an enum I deduce that such usage is rare.

I'll grant that your experience is probably much more broad than
mine (only one person ever called me an "expert," and that was
myself during a job interview  :-), but that doesn't mean it
neccesarily represents the whole C++ community.

For the record, I haven't needed a fowrard reference to an enum either.
But how about for a typedef that we know will eventually resolve to
some (possibly template) class? That, I strongly suspect, is not at
all rare.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 26 Sep 2002 16:49:59 +0000 (UTC)
Raw View
In article <3D92424B.24C03FE1@wizard.net>, James Russell Kuyper Jr.
<kuyper@wizard.net> writes
> (newsfep2-gui)
>
>Niklas Matthies wrote:
>....
>> The restriction seems to be that for those implementations where the
>> sizes of char* and int* are different, enums would have to be at least
>> of size int even if their range would fit into a char. Most likely
>> that's already the case anyway.
>
>I don't see how the size of pointers and the size of enumeration types
>are connected. Could you explain?

1) the size of a pointer to an enum type will depend on the size of the
enum type (if the sizeof(enumtype) is 1 it will need to use a pointer
that deals with packing several enums into a single address for computer
with direct addressing only available for 32-bit words for example)

2) All that forward declaration of a type allows is pointers to and
references to the type + declarations of yet to be defined, and not
called, functions.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: alisdair.meredith@uk.renaultf1.com (Alisdair Meredith)
Date: Thu, 26 Sep 2002 16:53:05 +0000 (UTC)
Raw View
> > I think he intends to use it the same way as any other forward
> > declaration; perhaps declaring a pointer to it, perhaps prototyping
> > a function that accepts it, and so on.

[This was very much my intent, especially wrt function prototypes]

Richard Smith wrote:

[A detailed explaination finishing with]

> Suppose I now want to link this a pair of translation units:
>
>      // Translation unit 1.
>      void foo( const int *i ) { delete i; }
>      const int *bar() { return new int(42); }
>
>      // Translation unit 2.
>      typedef int type;
>
> Translation unit 1 doesn't know anything about the name type, so the
> function foo, can only be emitted as a mangled version of
>
>      foo( const int * );
>
> ... which means that translation unit 2 needs to tell the linker about
> the typedef, and the linker needs to know how to interpret this.
>
> Most of C++ (although not all -- export and dynamic initialisation of
> namespace scope statics are obvious counter examples) is compatible with
> using relatively uninteligent 1970s-era linker technology.  In fact, the
>   desire to keep a clear division of functionality between the compiler
> and linker has been one of the major reasons that exported templates
> have taken so long to be supported.  If the linker were required to
> understand typedefs, it is likely that this would also take a long time
> to become supported for the same reasons.

Thanks for the clear explaination.
Not having to implement any of this myself, I am well aware that what
seems obvious from my limited view [it's just a small extension of...]
can have many subtle implications that the implementor cannot ignore.  I
certainly did not understand all the implications of what I had been
asking for.

I think this 'problem' I am trying to solve will become more apparent as
the community grows more familiar with template techniques.  Once
policy-based classes with multiple template paramters become
commonplace, typedefs will be something of a necessity.  Unfortunately,
as much template code is implemented directly in the included header
files including the information to supply the typedef frequently reveal
far more implementation details than would be desired.

It could be I am simply missing a better way to encapsulate my use of
templates, although typedef seems to be a pretty common tool here.

Now I understand the problem better, I shall go away an think some
more.  If this is to be anything like the exported templates problem
though [in fact, probably related] I suspect it will need finer minds
than mine to deliver a workable solution.
--
AlisdairM

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Thu, 26 Sep 2002 16:54:09 +0000 (UTC)
Raw View
kuyper@wizard.net ("James Russell Kuyper Jr.") wrote in message
news:<3D92424B.24C03FE1@wizard.net>...
> Niklas Matthies wrote:
> ....
> > The restriction seems to be that for those implementations where the
> > sizes of char* and int* are different, enums would have to be at
> > least of size int even if their range would fit into a char. Most
> > likely that's already the case anyway.

> I don't see how the size of pointers and the size of enumeration types
> are connected. Could you explain?

Presumably, if the underlying type of the enum is int, then the format
of the pointer will be the same as int*.

Formally, the standard *requires* an implementation to support different
underlying types for an enum.  An enum cannot be larger than an int
unless necessary.  But if necessary, obviously, it must be larger than
an int.  On a machine where int* and long* had different sizes, I don't
think you could implement a pointer to an enum except as compatible with
void* (which must be able to contain a pointer to anything).  This could
potentially represent an extra cost, but in practice, I don't think such
a machine exists (or has ever existed).

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pasa@lib.hu ("Balog Pal")
Date: Thu, 26 Sep 2002 17:14:40 +0000 (UTC)
Raw View
"Francis Glassborow" <francis.glassborow@ntlworld.com> wrote in message news:axZjIEsUTOk9EwsB@robinton.demon.co.uk...

> >> You see the problem is that different
> >> types have different size pointers (and quite possibly different ways of
> >> representing a reference),

I'd be perfectly happy to have 'class foo;' being accepted as a forward declaration when later foo happens to be a typedef of a (possibly templated) class. That has no conflict with pointer sizes.

And in my experience is a common need -- and becomes more frequent every day.  As the implementation code is being refactored, and what is a regular class today, tomorrow I generalize to a template, so the original class will be an instance of the template.  The rest of the program is unchanged, nothing notices it -- well discounting the headers with references to the class as incomplete type.    That is something bad.

> I did not say that. However enums are provided via some integer type and
> among the integer types we have char. On some systems pointers to char
> have a different size from pointer to int (and it is technically
> possible for pointer to short to be different to pointer to int, though
> I have never come across a system where that was so.)
> all forms of char* are required to be size and layout compatible with
> void*. All pointers to struct/class/union are required to be size and
> layout compatible with each other. Which is why forward declarations of
> class/struct/union types are permitted.

That could be solved easily. Stating a forward declaration of enum makes it as large as possible. (A plenty of implementations treat enums as ints anyway.)  So if it gets defined later, it will use that size, not a possibly smaller. And if you happen mess up, it's simply an ODR-issue.

MSVC allows forward declaring the enums, and use them as a _complete_ type afterwards. I use it for good, in some places, and got somewhat upset on a port to gcc, when I had to inconveniently extract my enum definition to a distinct file. (Thus proving it can be avoided, but I'd be more happy with the described behavior in practice.)

> iosfwd is a red herring. The need for it is related to the fact that
> those types are provided by templates and so cannot be forward declared
> by the user.

Yeah, see above.  And everyone gets hit by similar problems, and has to write redundant headers like iosfwd to solve his issues.

> The restriction that would be needed to allow forward declaration of
> enum types seems out of all proportion to the minuscule places where
> such would be of any use. Forward declaration allows pointers and
> references but not the type itself. As I have never come across using
> either for an enum I deduce that such usage is rare.

Yep, so the solution shall better be different for the enums.

Paul

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Thu, 26 Sep 2002 17:22:21 +0000 (UTC)
Raw View
kuyper@wizard.net ("James Russell Kuyper Jr.") wrote in message
news:<3D9105AA.7AF1CA3F@wizard.net>...
> Allan W wrote:

> > Alisdair Meredith <alisdair.meredith@uk.renaultf1.com> writes
>  ....
> > > You see the problem is that different types have different size
> > > pointers (and quite possibly different ways of representing a
> > > reference),

> > I believe that pointers to data are allowed to be different size
> > than a pointer to a function. Furthermore, a pointer-to-member is
> > almost always a different size than a pointer-to-free. And, if I
> > remember correctly, a pointer-to-void could potentially be different
> > than all of these.

> > That's a far cry from having a different size for every possible
> > pointer type!

> True. But you've barely scratched the surface of the variety of sizes
> allowed by the standard. In fact, there's very few pointer types that
> are required to be the same: Pointers to layout-compatible types that
> differ only in their cv-qualification must still have the same value
> representation and alignement requirements. So must char* and void*. I
> couldn't find any other pairs of pointer types that are required to be
> the same size.

> Actually, that surprises me - I thought that C++ shared the
> requirement that C has: "All pointers to structure types shall have
> the same representation and alignment requirements as each other. All
> pointers to union types shall have the same representation and
> alignment requirements as each other." Can someone locate the place
> where the C++ standard says something similar?

I don't think that this requirement was explicit in C90 (which is what
C++ is based on).  I think it was considered to be a requirement on the
grounds that no one could think of a possible implementation where it
didn't hold but that still worked in all cases of forward declarations.
(One possibility might be to use two different types of pointers,
according to the first letter of the structure tag.  But this creates
problems with layout-compatible structures.)

I think C++ just took over the wording of the then current C standard,
without really asking too many questions.  The fact that C++ doesn't
have layout-compatible types (I don't think) may mean that the trick
with the pointer size which depends on the first letter of the type name
is legal.  I really don't expect to see it in an actual implementation,
however.

In practice, the only different sized data pointers I've seen is for
char*/void* to be larger than all other pointer types.  But that's
pragmatics; as you say, the standard allows a lot more.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Russell Kuyper Jr.")
Date: Thu, 26 Sep 2002 17:45:33 +0000 (UTC)
Raw View
Allan W wrote:
....
> In practice, though, no data pointer is going to be larger than a
> void*. That's because it has to be possible to convert any pointer
> to void* and then back again without losing information.

No. It has to be possible to convert to void* and back without loosing
pointer identity. A pointer could carry additional information (such as
a counter that keeps track of how often the pointer's been used) that is
not used for evaluating "==". That information could be lost by a
conversion to void*, and reinitialized when it gets converted back. An
obscure possibility, I'll admit. I can't think of any good use for such
a feature, but I'm sure someone else could.

> > I don't have a clue what a pointer-to-free is.
>
> Okay, I didn't say it very well, but I think the context made it clear:
> : a pointer-to-member is almost always a different size than a
> : pointer-to-free.
> I meant, "a pointer to a non-member variable or function."

No - the context did not make it clear. What does "free" have to do with
"non-member variable or function"? My personal best guess had been that
you were talking about a pointer to free()'d memory, but that made no
sense, so I was completely baffled.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: news_comp.std.c++_expires-2002-10-01@nmhq.net (Niklas Matthies)
Date: Thu, 26 Sep 2002 17:46:33 +0000 (UTC)
Raw View
On Wed, 25 Sep 2002 23:25:18 +0000 (UTC), "James Russell Kuyper Jr." <kuyper@wizard.net> wrote:
>  Niklas Matthies wrote:
>  ....
> > The restriction seems to be that for those implementations where the
> > sizes of char* and int* are different, enums would have to be at least
> > of size int even if their range would fit into a char. Most likely
> > that's already the case anyway.
>
>  I don't see how the size of pointers and the size of enumeration types
>  are connected. Could you explain?

The point was made that there are implementations where the sizes of
char* and int* differ (presumably for the reason that the architecture's
"natural" pointers are word pointers, which requires byte pointers to
carry additional information), hence the sizes of pointers to char-sized
and to int-sized enums would differ as well.

-- Niklas Matthies
--
Save Farscape - get informed and involved: http://farscape.wdsection.com/
Together, we can get Farscape back on air. Crackers *do* matter.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Russell Kuyper Jr.")
Date: Thu, 26 Sep 2002 23:03:59 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> On Wed, 25 Sep 2002 23:25:18 +0000 (UTC), "James Russell Kuyper Jr." <kuyper@wizard.net> wrote:
> >  Niklas Matthies wrote:
> >  ....
> > > The restriction seems to be that for those implementations where the
> > > sizes of char* and int* are different, enums would have to be at least

^^^^^^^^^^^^^^^^^^^
> > > of size int even if their range would fit into a char. Most likely
      ^^^^^^^^^^^
> > > that's already the case anyway.
> >
> >  I don't see how the size of pointers and the size of enumeration types
> >  are connected. Could you explain?
>
> The point was made that there are implementations where the sizes of
> char* and int* differ (presumably for the reason that the architecture's
> "natural" pointers are word pointers, which requires byte pointers to
> carry additional information), hence the sizes of pointers to char-sized
> and to int-sized enums would differ as well.

Yes, but I don't see how that ends up prohibiting char-sized enums.
That's the connection that escapes me.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Tue, 24 Sep 2002 20:12:07 +0000 (UTC)
Raw View
Alisdair Meredith <alisdair.meredith@uk.renaultf1.com> writes
> >However, it seems to me that if we added a new
> >forward declaration syntax:
> >
> >typename aName;  // aName may be anything that behaves as a type
> >
> >it would be somewhat more flexible than the current system without
> >introducing any new keywords, although the parsing of typename just
> >became more 'interesting'.

francis.glassborow@ntlworld.com (Francis Glassborow) wrote
> How are you proposing to use such.

I think he intends to use it the same way as any other forward
declaration; perhaps declaring a pointer to it, perhaps prototyping
a function that accepts it, and so on.

> You see the problem is that different
> types have different size pointers (and quite possibly different ways of
> representing a reference),

I believe that pointers to data are allowed to be different size than
a pointer to a function. Furthermore, a pointer-to-member is almost
always a different size than a pointer-to-free. And, if I remember
correctly, a pointer-to-void could potentially be different than all
of these.

That's a far cry from having a different size for every possible pointer
type!

Consider <iosfwd>, an awkward solution to type typedefs in <iostream>.
But what if you wanted to declare a function that accepts a string,
without including <string>?

Worse still is when you don't know if something is a typedef or not.

In the spirit of Alisdair's proposal, perhaps we can find some way to
make "reasonable" assumptions without having to go all the way. I'm
sure that Alisdair doesn't care about the syntax so much as the
semantics -- if we can avoid having to #include every definition that
some program MIGHT use, we can avoid "header file hell".

> as you cannot use a forward declared type
> except as a reference or a through a pointer it seems that, in general,
> there is little purpose served in considering your proposal.

// myWidget.h
#ifndef included_myWidget.h
#define included_myWidget.h
typename VendorX::widget;
class myWidget {
public:
    // Convert VendorX widget to internal widget
    explicit myWidget(VendorX::widget&);

    // ...lots more stuff here...
};
#endif

If you know that VendorX::widget is a class, this works today. But if
it might be a typedef, you have to change this to include "vendorx.h"
directly. The issue goes well beyond the 90 extra minutes it now takes
for a full build. There's also namespace collisions, including the
lowercase macro names that VendorX thought were more readable (and you
have to live with it!) being included almost globally, instead of just
the 2 modules that included vendorx.h directly.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Wed, 25 Sep 2002 11:41:59 +0000 (UTC)
Raw View
> I believe that pointers to data are allowed to be different size than
> a pointer to a function.

Pointers to data are allowed to vary even between different types.
A pointer to void will be the same size as pointer to char.  They have
to be able to hold the converted value of any other object pointer.

I don't have a clue what a pointer-to-free is.




---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Wed, 25 Sep 2002 11:42:27 +0000 (UTC)
Raw View
In article <7f2735a5.0209241125.2be28661@posting.google.com>, Allan W
<allan_w@my-dejanews.com> writes
>> You see the problem is that different
>> types have different size pointers (and quite possibly different ways of
>> representing a reference),
>
>I believe that pointers to data are allowed to be different size than
>a pointer to a function. Furthermore, a pointer-to-member is almost
>always a different size than a pointer-to-free. And, if I remember
>correctly, a pointer-to-void could potentially be different than all
>of these.
>
>That's a far cry from having a different size for every possible pointer
>type!

I did not say that. However enums are provided via some integer type and
among the integer types we have char. On some systems pointers to char
have a different size from pointer to int (and it is technically
possible for pointer to short to be different to pointer to int, though
I have never come across a system where that was so.)
all forms of char* are required to be size and layout compatible with
void*. All pointers to struct/class/union are required to be size and
layout compatible with each other. Which is why forward declarations of
class/struct/union types are permitted.

iosfwd is a red herring. The need for it is related to the fact that
those types are provided by templates and so cannot be forward declared
by the user.


The restriction that would be needed to allow forward declaration of
enum types seems out of all proportion to the minuscule places where
such would be of any use. Forward declaration allows pointers and
references but not the type itself. As I have never come across using
either for an enum I deduce that such usage is rare.

--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: news_comp.std.c++_expires-2002-10-01@nmhq.net (Niklas Matthies)
Date: Wed, 25 Sep 2002 15:33:08 +0000 (UTC)
Raw View
On Wed, 25 Sep 2002 11:42:27 +0000 (UTC), Francis Glassborow <francis.glassborow@ntlworld.com> wrote:
>  In article <7f2735a5.0209241125.2be28661@posting.google.com>, Allan W
> <allan_w@my-dejanews.com> writes
> >> You see the problem is that different
> >> types have different size pointers (and quite possibly different ways of
> >> representing a reference),
> >
> >I believe that pointers to data are allowed to be different size than
> >a pointer to a function. Furthermore, a pointer-to-member is almost
> >always a different size than a pointer-to-free. And, if I remember
> >correctly, a pointer-to-void could potentially be different than all
> >of these.
> >
> >That's a far cry from having a different size for every possible pointer
> >type!
>
>  I did not say that. However enums are provided via some integer type
>  and among the integer types we have char. On some systems pointers to
>  char have a different size from pointer to int
[...]
>  The restriction that would be needed to allow forward declaration of
>  enum types seems out of all proportion to the minuscule places where
>  such would be of any use.

The restriction seems to be that for those implementations where the
sizes of char* and int* are different, enums would have to be at least
of size int even if their range would fit into a char. Most likely
that's already the case anyway.

-- Niklas Matthies
--
Save Farscape - get informed and involved: http://farscape.wdsection.com/
Together, we can get Farscape back on air. Crackers *do* matter.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Russell Kuyper Jr.")
Date: Wed, 25 Sep 2002 16:12:43 +0000 (UTC)
Raw View
Allan W wrote:
>
> Alisdair Meredith <alisdair.meredith@uk.renaultf1.com> writes
....
> > You see the problem is that different
> > types have different size pointers (and quite possibly different ways of
> > representing a reference),
>
> I believe that pointers to data are allowed to be different size than
> a pointer to a function. Furthermore, a pointer-to-member is almost
> always a different size than a pointer-to-free. And, if I remember
> correctly, a pointer-to-void could potentially be different than all
> of these.
>
> That's a far cry from having a different size for every possible pointer
> type!

True. But you've barely scratched the surface of the variety of sizes
allowed by the standard. In fact, there's very few pointer types that
are required to be the same: Pointers to layout-compatible types that
differ only in their cv-qualification must still have the same value
representation and alignement requirements. So must char* and void*. I
couldn't find any other pairs of pointer types that are required to be
the same size.

Actually, that surprises me - I thought that C++ shared the requirement
that C has: "All pointers to structure types shall have the same
representation and alignment requirements as each other. All pointers to
union types shall have the same representation and alignment
requirements as each other." Can someone locate the place where the C++
standard says something similar?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Wed, 25 Sep 2002 16:56:01 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0209241125.2be28661@posting.google.com>...
> Alisdair Meredith <alisdair.meredith@uk.renaultf1.com> writes
> > >However, it seems to me that if we added a new
> > >forward declaration syntax:

> > >typename aName;  // aName may be anything that behaves as a type

> > >it would be somewhat more flexible than the current system without
> > >introducing any new keywords, although the parsing of typename just
> > >became more 'interesting'.

> francis.glassborow@ntlworld.com (Francis Glassborow) wrote
> > How are you proposing to use such.

> I think he intends to use it the same way as any other forward
> declaration; perhaps declaring a pointer to it, perhaps prototyping a
> function that accepts it, and so on.

Declaring a pointer to it is the real problem.

> > You see the problem is that different types have different size
> > pointers (and quite possibly different ways of representing a
> > reference),

> I believe that pointers to data are allowed to be different size than
> a pointer to a function. Furthermore, a pointer-to-member is almost
> always a different size than a pointer-to-free. And, if I remember
> correctly, a pointer-to-void could potentially be different than all
> of these.

Pointers to members aren't pointers, so they don't pose a problem.  The
real problem is that C and C++ allow data pointers to have different
sizes.  In practice, I can't imagine more than two different sizes, but
I have worked on machines where char* was bigger than int*.  (The fact
that the C standard allows pointers to incomplete structs pretty much
implies that all pointers to a struct have the same size and layout.
Replace C with C++ and struct with class, and I think that the same
holds for C++.)

> That's a far cry from having a different size for every possible
> pointer type!

All you need is two different data type pointers.

> Consider <iosfwd>, an awkward solution to type typedefs in <iostream>.
> But what if you wanted to declare a function that accepts a string,
> without including <string>?

Agreed.  There should be some way of saying that something is a class
type, without specifying the actual name of the class, or whether the
class is an instantiation of a template or not.

Regretfully, I don't see how this would work with the current methods
used for typesafe linkage.  How can the linker know that my call to
f(std::string) is really a call to f(std::basic_string<char,...>) if the
compiler doesn't tell it?  And if std::string were just a forward
declaration, how could the compiler know that it is really a
std::basic_string<char,...>?

> Worse still is when you don't know if something is a typedef or not.

> In the spirit of Alisdair's proposal, perhaps we can find some way to
> make "reasonable" assumptions without having to go all the way. I'm
> sure that Alisdair doesn't care about the syntax so much as the
> semantics -- if we can avoid having to #include every definition that
> some program MIGHT use, we can avoid "header file hell".

> > as you cannot use a forward declared type except as a reference or a
> > through a pointer it seems that, in general, there is little purpose
> > served in considering your proposal.

> // myWidget.h
> #ifndef included_myWidget.h
> #define included_myWidget.h
> typename VendorX::widget;
> class myWidget {
> public:
>     // Convert VendorX widget to internal widget
>     explicit myWidget(VendorX::widget&);
>
>     // ...lots more stuff here...
> };
> #endif

> If you know that VendorX::widget is a class, this works today. But if
> it might be a typedef, you have to change this to include "vendorx.h"
> directly. The issue goes well beyond the 90 extra minutes it now takes
> for a full build. There's also namespace collisions, including the
> lowercase macro names that VendorX thought were more readable (and you
> have to live with it!) being included almost globally, instead of just
> the 2 modules that included vendorx.h directly.

The only solution I can see is for the library provider to furnish a
myWidget.fwd as well, along the lines of <iosfwd> with the forward
declarations which go with his classes, etc.  A solution which works
today.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: alisdair.meredith@uk.renaultf1.com (Alisdair Meredith)
Date: Sun, 22 Sep 2002 21:04:13 +0000 (UTC)
Raw View
In order to minimise dependencies in a header, we often forward declare
classes where their finer details are not needed.
Unfortunately this is not possible for typedefs, as forward declaring a
name intended for later typedefing clashes with the typedef itself.

When forward declaring such a name, we rarely care about the
implementation of whatever the name is, all we are trying to say is
'this name is the name of a type, please parse it accordingly' and
further details will be supplied if the translation unit needs them
[usually via another include]  We should not be hung up on 'is it a
class/typedef of class/typedef of something else (eg pointer)'

Given I am not a compiler implementor I am wary of making suggestions to
fix this problem, as I am aware C++ parsing rules are more than complex
enough already <g>  However, it seems to me that if we added a new
forward declaration syntax:

typename aName;  // aName may be anything that behaves as a type

it would be somewhat more flexible than the current system without
introducing any new keywords, although the parsing of typename just
became more 'interesting'.

Is there an idea worth pursuing here, or am I missing some reason why it
is desirable that typedefs should not be forward declarable?

--
AlisdairM

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: musiphil@bawi.org (Sungbom Kim)
Date: Mon, 23 Sep 2002 11:40:59 +0000 (UTC)
Raw View
Alisdair Meredith wrote:
>
> Given I am not a compiler implementor I am wary of making suggestions to
> fix this problem, as I am aware C++ parsing rules are more than complex
> enough already <g>  However, it seems to me that if we added a new
> forward declaration syntax:
>
> typename aName;  // aName may be anything that behaves as a type
>
> it would be somewhat more flexible than the current system without
> introducing any new keywords, although the parsing of typename just
> became more 'interesting'.
>
> Is there an idea worth pursuing here, or am I missing some reason why it
> is desirable that typedefs should not be forward declarable?

See my posting and its thread on this issue:
http://groups.google.com/groups?threadm=3D5E475F.EA6B7D4B%40bawi.org

--
Sungbom Kim <musiphil@bawi.org>

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Mon, 23 Sep 2002 14:37:20 +0000 (UTC)
Raw View
In article <3D8DAB57.E4BD4D8A@uk.renaultf1.com>, Alisdair Meredith
<alisdair.meredith@uk.renaultf1.com> writes
>When forward declaring such a name, we rarely care about the
>implementation of whatever the name is, all we are trying to say is
>'this name is the name of a type, please parse it accordingly' and
>further details will be supplied if the translation unit needs them
>[usually via another include]  We should not be hung up on 'is it a
>class/typedef of class/typedef of something else (eg pointer)'
>
>Given I am not a compiler implementor I am wary of making suggestions to
>fix this problem, as I am aware C++ parsing rules are more than complex
>enough already <g>  However, it seems to me that if we added a new
>forward declaration syntax:
>
>typename aName;  // aName may be anything that behaves as a type
>
>it would be somewhat more flexible than the current system without
>introducing any new keywords, although the parsing of typename just
>became more 'interesting'.
>
>Is there an idea worth pursuing here, or am I missing some reason why it
>is desirable that typedefs should not be forward declarable?

How are you proposing to use such. You see the problem is that different
types have different size pointers (and quite possibly different ways of
representing a reference), as you cannot use a forward declared type
except as a reference or a through a pointer it seems that, in general,
there is little purpose served in considering your proposal.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]