Topic: Subobject requires definition--why?


Author: spoon.menright@cts.com (Mike Enright)
Date: 1997/11/30
Raw View
"John I. Moore, Jr." <70672.1744@compuserve.com> wrote:

>Mark Wilden <Mark@mwilden.com> wrote in article
><346C9D29.10E3@mWilden.com>...
>> Can anyone give me a logical reason why this shouldn't compile?
>>
>>  struct A;
>>
>>  struct B {
>>    A a;
>>  };
>>
>> Neither the size of A nor knowledge of any of A's members is required.
>>
><....>
>you can most likely accomplish your goals by using a pointer to A.
>Consider the following:
>
>struct A;
>
>struct B {
>  A* a;
>};
>

Summary of thread:

while (1)
{
  Why don't we change C++ someday so I can do this?
  That code would be illegal C++ today, do something else.
}

Perhaps it would be more effective if a language implementation expert
would step in and say, "Implementing the proposal would be my worst
nightmare" or "It would be trivial to implement this".


--
Mike Enright
menright@cts.com
http://www.users.cts.com/sd/m/menright/
Cardiff-by-the-Sea, California, USA
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Mark Wilden <Mark@mwilden.com>
Date: 1997/12/01
Raw View
Since I started it, I'll add my own summary of this thread:

I wasn't suggesting that the standard be _changed_ to allow

 struct A;

 struct B;
    A a;
 };
 // EOF

I was just wondering if there was a _logical_ reason to prohibit it,
given the mnemonic that Stroustrup and others give that a class's
definition is unnecessary unless the size or names of its members are
needed (which is not the case above).

Valentin made that point that allowing the above would create a
declaration of a class that was defined but incomplete. This has nothing
to do with the "reasonable" size/name requirement, but it does indicate
a subtlety I hadn't considered.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Michael Ball <michael.ball@eng.sun.com>
Date: 1997/12/02
Raw View
Mike Enright wrote:
>
> "John I. Moore, Jr." <70672.1744@compuserve.com> wrote:
>
> >Mark Wilden <Mark@mwilden.com> wrote in article
> ><346C9D29.10E3@mWilden.com>...
> >> Can anyone give me a logical reason why this shouldn't compile?
> >>
> >>  struct A;
> >>
> >>  struct B {
> >>    A a;
> >>  };

> Perhaps it would be more effective if a language implementation expert
> would step in and say, "Implementing the proposal would be my worst
> nightmare" or "It would be trivial to implement this".

It would be neither.  It would require a significant reorganization
of many compilers and could result in some error messages' being
deferred until the type is used.

The utility is small (yes, I know some people argue about this)
and the cost is real, though not overwhelming in new development.
The cost could be significant in some existing compilers.

It also doesn't extend well to templates.

Mike Ball
Sun Microsystems Inc.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Pierre Baillargeon <pierre@ZAP_THISjazzmail.com>
Date: 1997/12/03
Raw View
Michael Ball wrote:

> Mike Enright wrote:
> >
> > "John I. Moore, Jr." <70672.1744@compuserve.com> wrote:
> >
> > >Mark Wilden <Mark@mwilden.com> wrote in article
> > ><346C9D29.10E3@mWilden.com>...
> > >> Can anyone give me a logical reason why this shouldn't compile?
> > >>
> > >>  struct A;
> > >>
> > >>  struct B {
> > >>    A a;
> > >>  };
>
> It would be neither.  It would require a significant reorganization
> of many compilers and could result in some error messages' being
> deferred until the type is used.

I did implement this in an ODL compiler, which was basically a C++
header file compiler. It doesn't add any complexity once you realize
that the deffered checks and validation are an exact equivalent of what
must be done for templates.

[...]

> It also doesn't extend well to templates.

Well, like I said, I rather think it extends very well.  In fact,
simply surrounding the example class B with a template<class A> prefix
does the trick. Of course, since most compilers require all template
code to be visible to be instantiated, you actually loose decoupling.
Oh well.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Andrew Fitzgibbon <awf@robots.ox.ac.uk>
Date: 1997/11/29
Raw View
Valentin Bonnard <bonnardv@pratique.fr> writes:
>
> Conclusion:
> - a type could be defined and incomplete
> - we must say that recursive definition are ill-formed,
>   and handle all weird cases
> - the user can get something better with a pointer A*
>
> So I think that we should put this in the TO DO list for
> C += ULONG_MAX.

C += numeric_limits<typeof C>::max()

Surely :)

A.

--
Andrew Fitzgibbon,                      awf@robots.ox.ac.uk
Oxford Information Engineering Research Group                +44 01865 273127
     <a href=http://www.robots.ox.ac.uk/~awf> Home Page </a>
    "Never say there is no way"
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Mark Wilden <Mark@mwilden.com>
Date: 1997/11/21
Raw View
John Potter wrote:
>
> What is the gain?

The gain is reduced compilation time.

If a header includes the definition of a class that is not used in a
given source file, and that class has a subobject, it won't be necessary
to recompile every source file that includes that header file if the
subobject definition changes.

Of course, in a perfect world, there would never be a situation like
this, but in the real world, it's a concern.

> : - the user can get something better with a pointer A*
>
> Agreed

If it were really true that pointers are always better than subobjects,
then subobjects should be eliminated from the language.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/11/22
Raw View
John Potter wrote:
>
> Valentin Bonnard <bonnardv@pratique.fr> wrote:
>
> : Well, someone could imagine that B is completed when A is:
                  ^^^^^^^^^^^^^

I should have written: could dream
but it would be close to a nightmare

> :  struct A; // A incomplete
> :
> :  struct B {
> :    A a;
> :  }; // B _defined_ but incomplete !
>
> I think that you must have given this some thought.  I can't see what
> could be done with an incomplete-defined that can not be done with a
> declared.

Defining B members (something that you could do after anyway),
but also calling the B members.

> : Conclusion:
> : - a type could be defined and incomplete
> : - we must say that recursive definition are ill-formed,
> :   and handle all weird cases
>
> What is the gain?

IMO nearly none

> : - the user can get something better with a pointer A*
>
> Agreed

A clarification is needed here: we both agree that using
a pointer A* solves the forward declaration problem better
(as B is really defined, not just declared) than allowing
an incomplete class to be included.

We don't say that all sub objects should be replaced
by a pointer.

> : So I think that we should put this in the TO DO list for
> : C += ULONG_MAX.
>
> Or is this an inside joke whose subtlety escapes me?

I forgot the smilley.   ;-)

I absolutly don't want to see that in the language.

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://www.pratique.fr/~bonnardv/
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Mark Wilden <Mark@mwilden.com>
Date: 1997/11/19
Raw View
John Potter wrote:
>
> Nope, but you *defined* a struct B which allowed me to define an
> object of that type.

Only by the current rules. Saying

 struct A;

doesn't allow you to define

 A a;

and the same could easily apply to an undefined subobject.

> :  struct A;
> :  size_t s = sizeof(A);
>
> Which is unknown!

Exactly! In other words, the kind of resulting error is not something
new.

>         typedef some_integral_type thingy;
>         struct C {
>                 thingy t;
>                 };
>
> Sometime later I will tell you whether some_integral_type is bool,
> char, short, long, (long long).  Does not compute.

This is a little different, since there is no such thing as an
incomplete typedef definition. There is such a thing as an incomplete
class definition.

 struct A;

Sometime later I will tell you how big A is and what its members are.
The computability is the same.

> I think I have a headache,

It really doesn't seem so difficult to me. The language would simply
follow its own mnemonic that the definition of a class is unnecessary
unless its size or member names need to be known. This is just logic.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Mark Wilden <Mark@mwilden.com>
Date: 1997/11/15
Raw View
Can anyone give me a logical reason why this shouldn't compile?

 struct A;

 struct B {
   A a;
 };

Neither the size of A nor knowledge of any of A's members is required.

This isn't just a theoretical concern for me. The ability to write such
code would reduce the number of header dependencies, hence compile time.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "John I. Moore, Jr." <70672.1744@compuserve.com>
Date: 1997/11/17
Raw View
Mark Wilden <Mark@mwilden.com> wrote in article
<346C9D29.10E3@mWilden.com>...
> Can anyone give me a logical reason why this shouldn't compile?
>
>  struct A;
>
>  struct B {
>    A a;
>  };
>
> Neither the size of A nor knowledge of any of A's members is required.
>
> This isn't just a theoretical concern for me. The ability to write such
> code would reduce the number of header dependencies, hence compile time.

This won't compile since it is not a complete defintion for B.  All
sizes of data members must be known in order to have a complete
definition.  Once B has been defined, you should be able to declare
objects, and the sizeof operator will work.  C++ doesn't support the
concept of partial definitions, only declarations (struct A;) and
definitions (similar to B, but not quite).

Two additional comments.  First, these declarations would normally be
placed in a header file, and therefore would not be compiled.  Second,
you can most likely accomplish your goals by using a pointer to A.
Consider the following:

struct A;

struct B {
  A* a;
};


_____________________________________________________________

John I. Moore, Jr.          phone:  (301) 924-0680
SoftMoore Consulting        email:  softmoore@compuserve.com
16233 Monty Court
Rockville, MD  20853-1344
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: hpa@transmeta.com (H. Peter Anvin)
Date: 1997/11/17
Raw View
Followup to:  <346C9D29.10E3@mWilden.com>
By author:    Mark Wilden <Mark@mwilden.com>
In newsgroup: comp.std.c++
>
> Can anyone give me a logical reason why this shouldn't compile?
>=20
>  struct A;
> =20
>  struct B {
>    A a;
>  };
>=20
> Neither the size of A nor knowledge of any of A's members is required.=20
>=20

Incorrect.  You need the size of struct A to know the size and
internal layout of struct B.

Perhaps you meant to do:

struct A;

struct B {
 A* a;
};

... which is legal...

 -hpa
--=20
    PGP: 2047/2A960705 BA 03 D3 2C 14 A8 A8 BD  1E DF FE 69 EE 35 BD 74
    See http://www.zytor.com/~hpa/ for web page and full PGP public key
        I am Bah=E1'=ED -- ask me about it or see http://www.bahai.org/
   "To love another person is to see the face of God." -- Les Mis=E9rable=
s
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Matt Pharr <mmp@graphics.stanford.edu>
Date: 1997/11/17
Raw View
hpa@transmeta.com (H. Peter Anvin) writes:
> By author:    Mark Wilden <Mark@mwilden.com>
> In newsgroup: comp.std.c++
> >
> > Can anyone give me a logical reason why this shouldn't compile?
> >
> >  struct A;
> >
> >  struct B {
> >    A a;
> >  };
> >
> > Neither the size of A nor knowledge of any of A's members is required.
> >
>
> Incorrect.  You need the size of struct A to know the size and
> internal layout of struct B.

I also thought "incorrect" at first, but I think his point is that so long
as you just have this declaration and don't actually use struct B, then you
don't need to know sizeof A.  This seems like the sort of thing a friendly
compiler might allow; is there any reason the ISO C++ standard (yaaaay!)
disallows it?

-matt
--
Matt Pharr                                   mmp@graphics.stanford.edu
<URL:http://www-graphics.stanford.edu/~mmp>
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/11/17
Raw View
John Potter <jpotter@falcon.lhup.edu> writes:

> Mark Wilden <Mark@mwilden.com> wrote:
>
> : Can anyone give me a logical reason why this shouldn't compile?
>
> :  struct A;
> :
> :  struct B {
> :    A a;
> :  };
>
> B b;
>
> : Neither the size of A nor knowledge of any of A's members is required.
>
> Ahh, what is sizeof(B) if sizeof(A) is not known?

Well, someone could imagine that B is completed when A is:

 struct A; // A incomplete

 struct B {
   A a;
 }; // B _defined_ but incomplete !

B x; // error
extern B x; // ok

struct A
{
    int x;
}; // A completed, B completed

B x; // ok

Conclusion:
- a type could be defined and incomplete
- we must say that recursive definition are ill-formed,
  and handle all weird cases
- the user can get something better with a pointer A*

So I think that we should put this in the TO DO list for
C += ULONG_MAX.

--

Valentin Bonnard                mailto:bonnardv@pratique.fr
info about C++/a propos du C++: http://www.pratique.fr/~bonnardv/
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Mark Wilden <Mark@mwilden.com>
Date: 1997/11/18
Raw View
Valentin Bonnard wrote:
>
> > Mark Wilden <Mark@mwilden.com> wrote:
> >
> > : Can anyone give me a logical reason why this shouldn't compile?
> >
> > :  struct A;
> > :
> > :  struct B {
> > :    A a;
> > :  };
> >
> > B b;

Woah! I didn't put that definition of b in there! :)

> > : Neither the size of A nor knowledge of any of A's members is required.
> >
> > Ahh, what is sizeof(B) if sizeof(A) is not known?

Since I'm not using sizeof(B), I don't see the relevance. But to answer
the question it would be equivalent to

 struct A;
 size_t s = sizeof(A);

> - a type could be defined and incomplete

That's an interesting point.

> - we must say that recursive definition are ill-formed,
>   and handle all weird cases

> - the user can get something better with a pointer A*

That doesn't necessarily follow. Subobjects of type T* are not always
better than type T, surely.

> So I think that we should put this in the TO DO list for
> C += ULONG_MAX.

Probably true. However, as I mentioned, my concern really is practical.
I've started working on a project that has been going on for four years,
and the header dependencies are incredible. To be able to replace
includes with incomplete class declarations wherever it makes logical
sense would be a real boon.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Mark Wilden <Mark@mwilden.com>
Date: 1997/11/18
Raw View
John I. Moore, Jr. wrote:
>
> >  struct A;
> >
> >  struct B {
> >    A a;
> >  };
>
> This won't compile since it is not a complete defintion for B.  All
> sizes of data members must be known in order to have a complete
> definition.  Once B has been defined, you should be able to declare
> objects, and the sizeof operator will work.

But I'm not declaring any objects and I'm not using the sizeof operator.

> C++ doesn't support the
> concept of partial definitions, only declarations (struct A;) and
> definitions (similar to B, but not quite).

My question was what is the logical _reason_ why my example isn't
allowed. The "commonsense" definition of where incomplete class
declarations are allowed to take the place of full class definitions is
when neither the size nor the members are used, which my example fits.

> Two additional comments.  First, these declarations would normally be
> placed in a header file, and therefore would not be compiled.

No, any code that would be compiled in a source file is compiled in a
header file.
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: jpotter@falcon.lhup.edu (John Potter)
Date: 1997/11/19
Raw View
Mark Wilden <Mark@mwilden.com> wrote:

: Valentin Bonnard wrote:
: >

Oops Val, I wrote:
: > John Potter wrote:

: > > Mark Wilden <Mark@mwilden.com> wrote:
: > >
: > > : Can anyone give me a logical reason why this shouldn't compile?
: > >
: > > :  struct A;
: > > :
: > > :  struct B {
: > > :    A a;
: > > :  };
      ^ Mark
    ^ John
  ^ Val
^ Mark
John

: > >
: > > B b;

: Woah! I didn't put that definition of b in there! :)

Nope, but you *defined* a struct B which allowed me to define an
object of that type.  You declared a struct A which did not allow me
to define an object of that type.  But you defined a struct B using
that undefined type.

: > > : Neither the size of A nor knowledge of any of A's members is required.
: > >
: > > Ahh, what is sizeof(B) if sizeof(A) is not known?

: Since I'm not using sizeof(B), I don't see the relevance. But to answer
: the question it would be equivalent to

:  struct A;
:  size_t s = sizeof(A);

Which is unknown!

How about
 typedef some_integral_type thingy;
 struct C {
  thingy t;
  };

Sometime later I will tell you whether some_integral_type is bool,
char, short, long, (long long).  Does not compute.

: > - a type could be defined and incomplete

: That's an interesting point.

Very interesting!  I would not like to write a compiler with those
rules; however, I don't have to.  I sure can understand why the
standard does not allow this sort of thing though.  A type can be
incomplete and declared but must be complete to be defined.  How about
void being defined?

I think I have a headache,
John
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]