Topic: Why not? typename for forward declarations


Author: kanze@gabi-soft.de
Date: 2000/06/25
Raw View
Ron Natalie <ron@sensor.com> writes:

|>  Steve Clamage wrote:

|>  > I hope you will agree that these are not "rare, pathological
|>  > implementations." :-)

|>  Not rare I'll agree, but I'll reserve my opinion on pathological :-)

Actually, if I recall Steve's post, the second case he sited where the
size of the enum depended on the enum values is required by the
standard.  The exact size of an enum is implementation defined, but
unless I'm mistaken, it cannot be gratuously larger than int.  Thus, on
a machine with 32 bit ints and 64 bit longs, the following enums are
*required* to have different sizes:

    enum MustHave32Bits { x =3D 1073741824 } ;
    enum MustHave64bits { y =3D 1152921504606846976 } ;

--=20
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Stephen Clamage <stephen.clamage@sun.com>
Date: 2000/06/26
Raw View
On Fri, 23 Jun 2000 03:56:10 CST, Mark Williams <markw65@my-deja.com>
wrote:

>In article <39514C81.94ACB943@sun.com>,
>  Steve Clamage <stephen.clamage@sun.com> wrote:
>> There could be any number of functions called foo in the program.
>>
>>  int foo(int&)
>>  int foo(bar&)
>>  int foo(std::basic_ostream<char,std::char_traits<char> >&)
>>  int foo(mynamespace::ostream&)
>>  int foo(yournamespace::ostream&)
>
>Namespaces are a red herring. The "typename" declaration would obviously
>declare a name in the current namespace.

Well, now you are modifying the original terms of discussion. The OP
just wanted to indicate that a name referred to an unspecified type.
I took that to mean the same thing it does in a template: nothing is
said about the full name or scope of the type.

>> In my example translation unit, there is a call to a foo that takes a
>> reference to some type locally identified only as "ostream".  No
>> other information is provided about the name "ostream". It might be
>> the name of a class or enum, or it might be a typedef for any type.
>
>True. But the one definition rule ensures that there is precisely one
>externally visible type with that name in the program, be it a typedef,
>a class or an enum. (If Im mistaken on this, then I withdraw my
>assertions, and accept your position)

Refer to 3.5. A typedef name referring to an unnamed class or enum at
namespace scope is the name used for that type for linkage purposes,
and in that case would have to be unique in that namespace. Otherwise,
a typedef name has no linkage. An object or function declared with a
typedef name has the linkage name associated with the type to which
the typedef name refers.

Since the typedef name need not be unique in the namespace across
translation units, there isn't any way to match the declaration with
the definition.

---
Steve Clamage, stephen.clamage@sun.com

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Mark Williams <markw65@my-deja.com>
Date: 2000/06/26
Raw View
In article <072bls0vid6em44iq1rs3rd2bphaf0cs3v@4ax.com>,
  stephen.clamage@sun.com wrote:
> On Fri, 23 Jun 2000 03:56:10 CST, Mark Williams <markw65@my-deja.com>
> wrote:
>
> >Namespaces are a red herring. The "typename" declaration would
obviously
> >declare a name in the current namespace.
>
> Well, now you are modifying the original terms of discussion. The OP
> just wanted to indicate that a name referred to an unspecified type.
> I took that to mean the same thing it does in a template: nothing is
> said about the full name or scope of the type.

Well, I cant read the OPs mind, but it seemed that he was asking for a
more general means of doing the traditional forward declaration - "class
X;" - in a way that works when X could actually be something other than
a plain class. It seems very odd to suppose that such an extension would
ignore namespaces...
>
> >> In my example translation unit, there is a call to a foo that takes
a
> >> reference to some type locally identified only as "ostream".  No
> >> other information is provided about the name "ostream". It might be
> >> the name of a class or enum, or it might be a typedef for any type.
> >
> >True. But the one definition rule ensures that there is precisely one
> >externally visible type with that name in the program, be it a
typedef,
> >a class or an enum. (If Im mistaken on this, then I withdraw my
> >assertions, and accept your position)
>
> Refer to 3.5. A typedef name referring to an unnamed class or enum at
> namespace scope is the name used for that type for linkage purposes,
> and in that case would have to be unique in that namespace. Otherwise,
> a typedef name has no linkage. An object or function declared with a
> typedef name has the linkage name associated with the type to which
> the typedef name refers.
>
> Since the typedef name need not be unique in the namespace across
> translation units, there isn't any way to match the declaration with
> the definition.

Yes, you are correct.

So what is needed is an equivalent to typedef that does have linkage.
Say

typename X; // declare X as an unknown type
typename X = Y; // declare X as a "typedef" to Y, which is guaranteed
unique in the namespace across translation units.

Of course to achieve what the OP was asking for, the standard library
would have to be re-written to use typename instead of typedef...

-------------
Mark Williams


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Mark Williams <markw65@my-deja.com>
Date: 2000/06/22
Raw View
In article <1ecboq4.142qdbr16mjcu1N%jthill@telus.net>,
  jthill@telus.net (Jim Hill) wrote:
> Mark Williams <markw65@my-deja.com> wrote:
>
> > All the other files just pass around references to ostream's.
>
> But references to char, char(*)() and struct { char a; } types may
each
> have different implementations. The compiler can't tell what to do
> without seeing at least that much.

As I pointed out in the part of the message you snipped, compilers are
already required to be able to support this - you can always pass around
void * pointers (I would not suggest allowing typename to predeclare a
pointer to function type). Allowing typename would provide a more
type-safe way of doing the same thing. It would cause some kind of
runtime overhead on the very few platforms where different types have
different pointer sizes; if you dont like that, you can take the compile
time overhead instead...

-------------
Mark Williams


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Mark Williams <markw65@my-deja.com>
Date: 2000/06/22
Raw View
In article <394A6BC8.7DF118BD@sun.com>,
  Steve Clamage <stephen.clamage@sun.com> wrote:
> Mark Williams wrote:

[snip]

> Suppose we allow typename as above. Here's a complete translation
unit:
>
> typename ostream;
> int foo(ostream&);
> int bar(ostream& o) { return foo(o); }
>
> In this example, ostream could be the name of a class,
> or a typedef for anything at all.  Under the C and C++ separate
> compilation model, where the definition of foo could be in a
> precompiled library without any source code provided, how can
> the compiler reliably generate the correct reference to foo?

You seem to assume that the only way of conveying such information to
the linker is by name mangling. Even if that is the case, the compiler
can pass on sufficient information to allow the linker to re-map
foo__F7ostream to foo__F27this_is_the_real_ostream.

Or is there an actual problem here that Ive overlooked?

-------------
Mark Williams


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Hyman Rosen <hymie@prolifics.com>
Date: 2000/06/22
Raw View
Mark Williams <markw65@my-deja.com> writes:
> You seem to assume that the only way of conveying such information to
> the linker is by name mangling. Even if that is the case, the compiler
> can pass on sufficient information to allow the linker to re-map
> foo__F7ostream to foo__F27this_is_the_real_ostream.
>
> Or is there an actual problem here that Ive overlooked?

Much like the pointer-before-the-array question, the standardizers
decided to support implementations that just used simple name
mangling instead of requiring something more complicated so that
the suggested idiom could be supported.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: smeyers@aristeia.com (Scott Meyers)
Date: 2000/06/22
Raw View
On Sun, 18 Jun 2000 08:34:44 CST, James Kuyper wrote:
> Problem: until the definition of SomeEnum is visible, the compiler has
> no way of know what size it will be, nor even (on many implementations)
> what size the pointers to it will be.

Can you give me some examples of such implementations?  I'm not challenging
your claim, just curious about it.  If you'd said "some" implementations, I'd
have translated that into "rare, pathological implementations," but "many" is
a stronger claim, so I'm curious about it.

Thanks,

Scott

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Steve Clamage <stephen.clamage@sun.com>
Date: 2000/06/22
Raw View
Scott Meyers wrote:
>
> On Sun, 18 Jun 2000 08:34:44 CST, James Kuyper wrote:
> > Problem: until the definition of SomeEnum is visible, the compiler has
> > no way of know what size it will be, nor even (on many implementations)
> > what size the pointers to it will be.
>
> Can you give me some examples of such implementations?

The standard requires that enums be implemented as integer types,
but allows different integer types for different enums.

The original Borland C++ compiler used the smallest integer type
that could contain all the enumerators:
 enum A { a, b }; // implemented as char
 enum C { c=-1, d=129 }; // implemented as 16-bit int
You could use a command-line switch to force enums to int type.
I don't know whether this is still the case for the current
Borland compilers.

The current Sun C++ compilers implement an enum as a 32-bit type
unless an enumerator won't fit in 32 bits. It implements such
enums as a 64-bit type.

I hope you will agree that these are not "rare, pathological
implementations." :-)

--
Steve Clamage, stephen.clamage@sun.com

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 2000/06/22
Raw View
Scott Meyers wrote:
>
> On Sun, 18 Jun 2000 08:34:44 CST, James Kuyper wrote:
> > Problem: until the definition of SomeEnum is visible, the compiler has
> > no way of know what size it will be, nor even (on many implementations)
> > what size the pointers to it will be.
>
> Can you give me some examples of such implementations?  I'm not challenging
> your claim, just curious about it.  If you'd said "some" implementations, I'd
> have translated that into "rare, pathological implementations," but "many" is
> a stronger claim, so I'm curious about it.

I was being careless; personally I don't know any implementations that
have differently sized pointers for pointers to different types of
objects. I know they exist only because other people have mentioned
them. I've no idea how common they are. However, I make a point of never
assuming that any two pointers to different types of objects are the
same size. It's not an assumption you ever really need. 'void *' is the
key to avoiding any need for such assumptions.

On the other hand, implementations where different enumerated types have
different sizes are quite commonplace, and that's an equally big problem
in this context.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: kanze@gabi-soft.de
Date: 2000/06/23
Raw View
Steve Clamage <stephen.clamage@sun.com> writes:

|>  Scott Meyers wrote:

|>  > On Sun, 18 Jun 2000 08:34:44 CST, James Kuyper wrote:
|>  > > Problem: until the definition of SomeEnum is visible, the
|>  > > compiler has no way of know what size it will be, nor even (on
|>  > > many implementations) what size the pointers to it will be.

|>  > Can you give me some examples of such implementations?=20

|>  The standard requires that enums be implemented as integer types,
|>  but allows different integer types for different enums.

|>  The original Borland C++ compiler used the smallest integer type
|>  that could contain all the enumerators:
|>   enum A { a, b }; // implemented as char
|>   enum C { c=3D-1, d=3D129 }; // implemented as 16-bit int
|>  You could use a command-line switch to force enums to int type.
|>  I don't know whether this is still the case for the current
|>  Borland compilers.

|>  The current Sun C++ compilers implement an enum as a 32-bit type
|>  unless an enumerator won't fit in 32 bits. It implements such
|>  enums as a 64-bit type.

|>  I hope you will agree that these are not "rare, pathological
|>  implementations." :-)

I understood Scott's question to refer to James Kuyper's remark about
not knowing what size the pointers to the enum will be (on many
implementations).  In the two implementations above, all data pointers
are the same size.

I'm aware of quite a bit of hardware where char* would be bigger than
other pointers.  It's all pretty old, though, and I have no idea whether
there are really C++ implementations for it.  (For some, I know that
there aren't.  They material went out of production somewhere around
1975.  For others, however, I don't know.)

--=20
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: kanze@gabi-soft.de
Date: 2000/06/23
Raw View
smeyers@aristeia.com (Scott Meyers) writes:

|>  On Sun, 18 Jun 2000 08:34:44 CST, James Kuyper wrote:
|>  > Problem: until the definition of SomeEnum is visible, the compiler
|>  > has no way of know what size it will be, nor even (on many
|>  > implementations) what size the pointers to it will be.

|>  Can you give me some examples of such implementations?  I'm not
|>  challenging your claim, just curious about it.  If you'd said "some"
|>  implementations, I'd have translated that into "rare, pathological
|>  implementations," but "many" is a stronger claim, so I'm curious
|>  about it.

Historically, I think most architectures were word addressed, and so a
char* was bigger than an int*.  That's historically, however -- I don't
know how many of these historical architectures are still being sold, or
have a C++ implementation.

--=20
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient=E9e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh=FCttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Steve Clamage <stephen.clamage@sun.com>
Date: 2000/06/23
Raw View
Mark Williams wrote:
>
> In article <394A6BC8.7DF118BD@sun.com>,
>   Steve Clamage <stephen.clamage@sun.com> wrote:
> > Mark Williams wrote:
>
> > Suppose we allow typename as above. Here's a complete translation
> unit:
> >
> > typename ostream;
> > int foo(ostream&);
> > int bar(ostream& o) { return foo(o); }
> >
> > In this example, ostream could be the name of a class,
> > or a typedef for anything at all.  Under the C and C++ separate
> > compilation model, where the definition of foo could be in a
> > precompiled library without any source code provided, how can
> > the compiler reliably generate the correct reference to foo?
>
> You seem to assume that the only way of conveying such information to
> the linker is by name mangling. Even if that is the case, the compiler
> can pass on sufficient information to allow the linker to re-map
> foo__F7ostream to foo__F27this_is_the_real_ostream.

Notice that I did not mention name mangling.

There could be any number of functions called foo in the program.

 int foo(int&)
 int foo(bar&)
 int foo(std::basic_ostream<char,std::char_traits<char> >&)
 int foo(mynamespace::ostream&)
 int foo(yournamespace::ostream&)

In my example translation unit, there is a call to a foo that takes a
reference to some type locally identified only as "ostream".  No
other information is provided about the name "ostream". It might be
the name of a class or enum, or it might be a typedef for any type.

Which of the above definitions of foo, if any, should be linked to
the function call?  There is no way to know, because there is not
enough information in this translation unit.

The C++ rule is that the name ostream must have a type declaration.
With the declaration present, the compiler can generate enough
information to enable the function reference to be matched to the
function definition:

 class bar;
 typedef bar ostream;
 int foo(ostream&); // Now we know it is foo(bar&)

--
Steve Clamage, stephen.clamage@sun.com

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Ron Natalie <ron@sensor.com>
Date: 2000/06/23
Raw View

Steve Clamage wrote:
>
>
> I hope you will agree that these are not "rare, pathological
> implementations." :-)
>
Not rare I'll agree, but I'll reserve my opinion on pathological :-)

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Mark Williams <markw65@my-deja.com>
Date: 2000/06/23
Raw View
In article <39514C81.94ACB943@sun.com>,
  Steve Clamage <stephen.clamage@sun.com> wrote:
> Mark Williams wrote:
> >
> > In article <394A6BC8.7DF118BD@sun.com>,
> >   Steve Clamage <stephen.clamage@sun.com> wrote:
> > > Mark Williams wrote:
> >
> > > Suppose we allow typename as above. Here's a complete translation
> > unit:
> > >
> > > typename ostream;
> > > int foo(ostream&);
> > > int bar(ostream& o) { return foo(o); }
> > >
> > > In this example, ostream could be the name of a class,
> > > or a typedef for anything at all.  Under the C and C++ separate
> > > compilation model, where the definition of foo could be in a
> > > precompiled library without any source code provided, how can
> > > the compiler reliably generate the correct reference to foo?
> >
> > You seem to assume that the only way of conveying such information
to
> > the linker is by name mangling. Even if that is the case, the
compiler
> > can pass on sufficient information to allow the linker to re-map
> > foo__F7ostream to foo__F27this_is_the_real_ostream.
>
> Notice that I did not mention name mangling.

No, but I couldnt think what else you could be getting at. And Im still
at a loss to be honest.

>
> There could be any number of functions called foo in the program.
>
>  int foo(int&)
>  int foo(bar&)
>  int foo(std::basic_ostream<char,std::char_traits<char> >&)
>  int foo(mynamespace::ostream&)
>  int foo(yournamespace::ostream&)

Namespaces are a red herring. The "typename" declaration would obviously
declare a name in the current namespace.

>
> In my example translation unit, there is a call to a foo that takes a
> reference to some type locally identified only as "ostream".  No
> other information is provided about the name "ostream". It might be
> the name of a class or enum, or it might be a typedef for any type.

True. But the one definition rule ensures that there is precisely one
externally visible type with that name in the program, be it a typedef,
a class or an enum. (If Im mistaken on this, then I withdraw my
assertions, and accept your position)

>
> Which of the above definitions of foo, if any, should be linked to
> the function call?  There is no way to know, because there is not
> enough information in this translation unit.

But the linker isnt restricted to looking at "this" translation unit.
Its looking at all of them. And that was my point. In at least one
translation unit, the compiler must have put out a typedef, class or
enum definition with the name "ostream". When the linker sees that, it
knows how to remap the typename declaration.

>
> The C++ rule is that the name ostream must have a type declaration.
> With the declaration present, the compiler can generate enough
> information to enable the function reference to be matched to the
> function definition:
>
>  class bar;
>  typedef bar ostream;
>  int foo(ostream&); // Now we know it is foo(bar&)
>

And without the declaration present, it can also generate enough
information to enable the function reference to be matched to the
function definition...

-------------
Mark Williams


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: smeyers@aristeia.com (Scott Meyers)
Date: 2000/06/24
Raw View
On Thu, 22 Jun 2000 22:46:48 CST, Steve Clamage wrote:
> The standard requires that enums be implemented as integer types,
> but allows different integer types for different enums.

Sorry, I meant the pointers to the enums, not the enums themselves.

Scott

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: jthill@telus.net (Jim Hill)
Date: 2000/06/18
Raw View
Mark Williams <markw65@my-deja.com> wrote:

> All the other files just pass around references to ostream's.

But references to char, char(*)() and struct { char a; } types may each
have different implementations. The compiler can't tell what to do
without seeing at least that much.

Jim

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Dirk Schreib" <Dirk.Schreib@uumail.de>
Date: 2000/06/18
Raw View
Ron Natalie <ron@sensor.com> wrote in message
news:394A4110.CBFA394D@sensor.com...
>
> Dirk Schreib wrote:
> >
> > The same is true for some types, which are implemented as enums.
> >
> You can't have incomplete definition of enums anyhow.
>
> What are you going to do with it?  A partial enum declaration is pretty
useless.

I don't think so. For example:

SomeClass.h:

typename SomeEnum;

class SomeClass
{
public:
    const SomeEnum& getSome() const;
    void SetSome( SomeEnum& se );
// or
    void SetSomePtr( SomeEnum* se );
};

SomeClass.cpp:
#include <SomeClass.h>
#include <SomeEnum.h> // defines SomeEnum

const SomeEnum& SomeClass::getSome() const
{ ... };
etc.

Ciao
  Dirk



---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Dirk Schreib" <Dirk.Schreib@uumail.de>
Date: 2000/06/18
Raw View
Steve Clamage <stephen.clamage@sun.com> wrote in message
news:394A6BC8.7DF118BD@sun.com...
> Mark Williams wrote:
> >
> > In article <394A1AD6.AFC2A9B3@wizard.net>,
> >   James Kuyper <kuyper@wizard.net> wrote:
> > > Dirk Schreib wrote:
> > > > Why isn't it possible to write:
> > > >
> > > > typename ostream;
> > > > or
> > > > typename some_enum;
>[...]
> Suppose we allow typename as above. Here's a complete translation unit:
>
> typename ostream;
> int foo(ostream&);
> int bar(ostream& o) { return foo(o); }
>
> In this example, ostream could be the name of a class,
> or a typedef for anything at all.  Under the C and C++ separate
> compilation model, where the definition of foo could be in a
> precompiled library without any source code provided, how can
> the compiler reliably generate the correct reference to foo?

Your example needs an #include <iostream> (not <iosfwd>) anyway:

typename ostream;
int foo(ostream&);        // should be ok
int bar(ostream& o) { return foo(o); }  // error: use of "uncomplete" o

but the following code could be possible:

something.h:
typename ostream;
int foo(ostream&);        // should be ok
int bar(ostream& o);    // should be ok

something.cpp:
#include "something.h"
#include <iostream>
int bar(ostream& o) { return foo(o); }  // ok: compiler knows everything
about ostream

Ciao
  Dirk



---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 2000/06/18
Raw View
Dirk Schreib wrote:
>
> Ron Natalie <ron@sensor.com> wrote in message
> news:394A4110.CBFA394D@sensor.com...
> >
> > Dirk Schreib wrote:
> > >
> > > The same is true for some types, which are implemented as enums.
> > >
> > You can't have incomplete definition of enums anyhow.
> >
> > What are you going to do with it?  A partial enum declaration is pretty
> useless.
>
> I don't think so. For example:
>
> SomeClass.h:
>
> typename SomeEnum;
>
> class SomeClass
> {
> public:
>     const SomeEnum& getSome() const;
>     void SetSome( SomeEnum& se );
> // or
>     void SetSomePtr( SomeEnum* se );
> };
>
> SomeClass.cpp:
> #include <SomeClass.h>
> #include <SomeEnum.h> // defines SomeEnum
>
> const SomeEnum& SomeClass::getSome() const
> { ... };
> etc.

Problem: until the definition of SomeEnum is visible, the compiler has
no way of know what size it will be, nor even (on many implementations)
what size the pointers to it will be. Even the functions that take
reference arguments really take pointer arguments, if you look at the
typical implementation of references. Therefore, a compiler can't
properly resolve calls to the member functions until the definition of
SomeEnum is visible. Therefore, there's very little you can do with
SomeClass until it is. There's correspondingly little advantage to being
able to declare SomeClass without being having to declare SomeEnum.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Steve Clamage <stephen.clamage@sun.com>
Date: 2000/06/20
Raw View
Dirk Schreib wrote:
>
> Steve Clamage <stephen.clamage@sun.com> wrote in message
> news:394A6BC8.7DF118BD@sun.com...
> > Mark Williams wrote:
> > >
> > > In article <394A1AD6.AFC2A9B3@wizard.net>,
> > >   James Kuyper <kuyper@wizard.net> wrote:
> > > > Dirk Schreib wrote:
> > > > > Why isn't it possible to write:
> > > > >
> > > > > typename ostream;
> > > > > or
> > > > > typename some_enum;
> >[...]
> > Suppose we allow typename as above. Here's a complete translation unit:
> >
> > typename ostream;
> > int foo(ostream&);
> > int bar(ostream& o) { return foo(o); }
> >
> > In this example, ostream could be the name of a class,
> > or a typedef for anything at all.  Under the C and C++ separate
> > compilation model, where the definition of foo could be in a
> > precompiled library without any source code provided, how can
> > the compiler reliably generate the correct reference to foo?
>
> Your example needs an #include <iostream> (not <iosfwd>) anyway:

No, the header <iosfwd> was created specifically for this kind of
situation.  Of course, type ostream is really std::ostream, so you'd
need to take care of that by one method or another. Here's a valid
version of the fragment:

#include <iosfwd>
using std::ostream;
int foo(ostream&);
int bar(ostream& o) { return foo(o); }

If your compiler doesn't like this, complain to the vendor. Since
neither the size nor the content of the underlying type of
std::ostream needs to be known, no definition of the type needs
to be seen.

But this is all irrelevant. I was answering the question, "Why must I
include any headers?  Why can't the compiler just take "ostream" as
the name of the type and be happy with that?"

--
Steve Clamage, stephen.clamage@sun.com

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Dirk Schreib" <Dirk.Schreib@uumail.de>
Date: 2000/06/16
Raw View
With standard C++ it is no longer possible
to declare e.g.

class ostream;

instead of this you have to include <iosfwd> because
ostream is no longer a class but a typedef to a template class.

The same is true for some types, which are implemented as enums.

Why isn't it possible to write:

typename ostream;
or
typename some_enum;

it fits very well in the meaning of typename (it just works only inside a
template)
and you don't need to know some implementation detail for
a forward declaration.

Ciao
  Dirk





---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 2000/06/16
Raw View
Dirk Schreib wrote:
>
> With standard C++ it is no longer possible
> to declare e.g.
>
> class ostream;
>
> instead of this you have to include <iosfwd> because
> ostream is no longer a class but a typedef to a template class.
>
> The same is true for some types, which are implemented as enums.
>
> Why isn't it possible to write:
>
> typename ostream;
> or
> typename some_enum;
>
> it fits very well in the meaning of typename (it just works only inside a
> template)
> and you don't need to know some implementation detail for
> a forward declaration.

What makes 'typename' feasible in a template context is instantiation.
You don't need the full details of the type at template definition time,
but you do need them before the template is instantiated for a
particular type. What you're suggesting leaves out the details entirely,
unless you #include <iosfwd> somewhere else farther down in the
translation unit. If you've got to #include <iosfwd> somewhere along the
line anyway, why not do so instead of your "typename ostream;"
statement?

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Mark Williams <markw65@my-deja.com>
Date: 2000/06/17
Raw View
In article <394A1AD6.AFC2A9B3@wizard.net>,
  James Kuyper <kuyper@wizard.net> wrote:
> Dirk Schreib wrote:
> > Why isn't it possible to write:
> >
> > typename ostream;
> > or
> > typename some_enum;
[snip]
>
> What makes 'typename' feasible in a template context is instantiation.
> You don't need the full details of the type at template definition
time,
> but you do need them before the template is instantiated for a
> particular type. What you're suggesting leaves out the details
entirely,
> unless you #include <iosfwd> somewhere else farther down in the
> translation unit. If you've got to #include <iosfwd> somewhere along
the
> line anyway, why not do so instead of your "typename ostream;"
> statement?

Because I may not have to. I could have all the code to actually produce
output, and to open,close and otherwise manipluate streams in one file,
which clearly needs <iostream>. All the other files just pass around
references to ostream's. None of them needs more than a "placeholder"
definition of ostream. In fact, if you hide the name using a typedef,
they dont even need to know its an ostream - that way, you can change
the implementation with no impact on the users.

It is currently possible to do this (in a totally type-unsafe way) by
passing void* pointers around, and casting back to ostream* at the point
of use. This is, I believe, standard conforming, since a pointer to
ostream is being cast to void* and back again. So implementation of such
a feature is clearly possible.

Its also desirable in that it can reduce compile times, not to mention
reducing inter-module dependencies.

-------------
Mark Williams


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Ron Natalie <ron@sensor.com>
Date: 2000/06/17
Raw View

Dirk Schreib wrote:
>
> The same is true for some types, which are implemented as enums.
>
You can't have incomplete definition of enums anyhow.

What are you going to do with it?  A partial enum declaration is pretty useless.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Steve Clamage <stephen.clamage@sun.com>
Date: 2000/06/17
Raw View
Mark Williams wrote:
>
> In article <394A1AD6.AFC2A9B3@wizard.net>,
>   James Kuyper <kuyper@wizard.net> wrote:
> > Dirk Schreib wrote:
> > > Why isn't it possible to write:
> > >
> > > typename ostream;
> > > or
> > > typename some_enum;
> [snip]
> >
> > What makes 'typename' feasible in a template context is instantiation.
> > You don't need the full details of the type at template definition
> time,
> > but you do need them before the template is instantiated for a
> > particular type. What you're suggesting leaves out the details
> entirely,
> > unless you #include <iosfwd> somewhere else farther down in the
> > translation unit. If you've got to #include <iosfwd> somewhere along
> the
> > line anyway, why not do so instead of your "typename ostream;"
> > statement?
>
> Because I may not have to. I could have all the code to actually produce
> output, and to open,close and otherwise manipluate streams in one file,
> which clearly needs <iostream>. All the other files just pass around
> references to ostream's.

The compiler must generate a reference to an external function
that corresponds to the definition of the function in question.
To ensure that all generated references to the same function
are the same, compilers "expand" all typedefs down to
primitive or user-defined types.

For example, all the following declarations of f must considered
to be identical:
 typedef int I;
 typedef I J;
 void f(int, int);
 void f(int, I);
 void f(J, int);
 void f(I, J);
 void f(J, I);
No matter which declaration of f the compiler sees, it generates
a reference to f(int,int). No matter what combination of I, J, and
int appear in the definition of f, the definition is treated
as f(int, int). Now everything matches up properly.

Suppose we allow typename as above. Here's a complete translation unit:

typename ostream;
int foo(ostream&);
int bar(ostream& o) { return foo(o); }

In this example, ostream could be the name of a class,
or a typedef for anything at all.  Under the C and C++ separate
compilation model, where the definition of foo could be in a
precompiled library without any source code provided, how can
the compiler reliably generate the correct reference to foo?

--
Steve Clamage, stephen.clamage@sun.com

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]