Topic: Address of reference to incomplete type (probably DR)


Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Wed, 27 Jun 2001 19:36:42 GMT
Raw View
"Sergey P. Derevyago" wrote:
>
> "Igor A. Goussarov" wrote:
>
> > The possible ways are:
> > 1. Disallow taking address of references to objects of incomplete type.
>         This one. And not only...
>
> > 2. Disallow references to objects of incomplete type themselves.
>         A very bad idea :)
>
> >    What exactly are you after?
> >    To me 2) seems to be way too heavy weapon for this bug, 1) seems to
> > affect the symmetry of taking address - dereference operations.
>         IMHO this symmetry should not be taken into account. You can't do anything
> "interesting" with reference if you don't know exactly what the object
> really is. In principle, references emulate objects.

   IMHO taking away this symmetry will lead to very unpleasant results.
Let's imagine that taking of address of references to incomplete type
(=RIT) is forbidden. Thus, once converted to a reference, the pointer is
stuck in this form and there's no way to obtain the original pointer
back. So if one has obtained a RIT as hanlde he cannot use it to call
functions that are designed to take PIT. This means that
_all_over_the_project_ (!) the objects should be passes either via
pointers or via references*. No mix. And what about third party code and
libraries? Especially when one of them is designed to use pointers and
another one - to use references?
   Of course, not so many classes are used in their incomplete form...
But creating two distinct ways to implement handlers of incomplete type
and disallow free conversion from one form to another will (IMHO) cause
more troubles then one might have with current state of the game.
   So I believe that disallowing reference-to-pointer conversion for
incomplete types is as bad as disallowing such references themselves.

*) Passing by value is not applicable here and thus not considered.

> >    If you let me express my own opinion, then after
> >
> > class Incomplete;
> > Incomplete*    p = ...;
> > Incomplete&    r = *p;
> >
> > &r should evaluates back to the value of p (i.e. &r == p).
>         IMHO no, because it's too dangerous. Probably, you have a _very_ good
> reason if you've defined operator&(). So, am I allowed to ignore it?!

   Why of course you are! The reasons might be very serious. But if '&'
is applied to an incomplete type reference its intention is likely to
take object's address, not to call any object-defined operator.
   My point is: if some class was intentionally left incomplete and the
pointers/references to it are used, then aforementioned pointers should
remain invariant as long as the client code does not know about the
complete type and thus can only pass these pointers to some other
functions or convert them to/from references. Whatever good reason one
might have, an overloaded operator& could possibly alter the value
during reference-to-pointer conversion, which break the concept of
invariant handlers.

Igor

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: jk@steel.orel.ru (Eugene Karpachov)
Date: Thu, 28 Jun 2001 09:45:05 GMT
Raw View
Wed, 27 Jun 2001 19:36:42 GMT Igor A. Goussarov =CE=C1=D0=C9=D3=C1=CC:
>   IMHO taking away this symmetry will lead to very unpleasant results.
>Let's imagine that taking of address of references to incomplete type
>(=3DRIT) is forbidden. Thus, once converted to a reference, the pointer =
is
>stuck in this form and there's no way to obtain the original pointer
>back. So if one has obtained a RIT as hanlde he cannot use it to call
>functions that are designed to take PIT. This means that

You can't use it anyway because type is incomplete and you don't know if =
you
can take *real* address from this reference.

>   Why of course you are! The reasons might be very serious. But if '&'
>is applied to an incomplete type reference its intention is likely to
>take object's address, not to call any object-defined operator.=20

Yes, but it cannot help.

>   My point is: if some class was intentionally left incomplete and the
>pointers/references to it are used, then aforementioned pointers should
>remain invariant as long as the client code does not know about the
>complete type and thus can only pass these pointers to some other
>functions or convert them to/from references. Whatever good reason one

So code semantics will change depending from some header inclusion?
Not a good idea IMHO.=20

IMHO overloading of operator& was very bad idea, but, as usual :(, it is =
to
late now to fix it.

--=20
jk

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Thu, 28 Jun 2001 15:05:36 GMT
Raw View
"Igor A. Goussarov" wrote:
>
> "Sergey P. Derevyago" wrote:
> >
> > "Igor A. Goussarov" wrote:
...
> >         IMHO no, because it's too dangerous. Probably, you have a _very_ good
> > reason if you've defined operator&(). So, am I allowed to ignore it?!
>
>    Why of course you are! The reasons might be very serious. But if '&'
> is applied to an incomplete type reference its intention is likely to
> take object's address, not to call any object-defined operator.

And, if operator&() is defined, it's presumably the developer's
intention to prevent anyone from taking the address; presumably for some
good reason. Therefore, you're bypassing the developer's intent, which
is at best a fairly dangerous proposition. That's why it's undefined
behavior. Whatever the reason was why operator&() was overloaded, any
situation like this where it should be invoked, but can't be, is likely
to be one that will cause that reason to be violated.

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Thu, 28 Jun 2001 15:05:25 GMT
Raw View
"Igor A. Goussarov" <igusarov@akella.com> wrote in message
news:3B3A1A21.36FA14D0@akella.com...
> "Sergey P. Derevyago" wrote:
> >
> > "Igor A. Goussarov" wrote:
> >
> > > The possible ways are:
> > > 1. Disallow taking address of references to objects of incomplete
type.
> >         This one. And not only...
> >
> > > 2. Disallow references to objects of incomplete type themselves.
> >         A very bad idea :)
> >
> > >    What exactly are you after?
> > >    To me 2) seems to be way too heavy weapon for this bug, 1) seems to
> > > affect the symmetry of taking address - dereference operations.
> >         IMHO this symmetry should not be taken into account. You can't
do anything
> > "interesting" with reference if you don't know exactly what the object
> > really is. In principle, references emulate objects.
>
>    IMHO taking away this symmetry will lead to very unpleasant results.
> Let's imagine that taking of address of references to incomplete type
> (=RIT) is forbidden. Thus, once converted to a reference, the pointer is
> stuck in this form and there's no way to obtain the original pointer
> back. So if one has obtained a RIT as hanlde he cannot use it to call
> functions that are designed to take PIT. This means that
> _all_over_the_project_ (!) the objects should be passes either via
> pointers or via references*. No mix. And what about third party code and
> libraries? Especially when one of them is designed to use pointers and
> another one - to use references?
>    Of course, not so many classes are used in their incomplete form...
> But creating two distinct ways to implement handlers of incomplete type
> and disallow free conversion from one form to another will (IMHO) cause
> more troubles then one might have with current state of the game.
>    So I believe that disallowing reference-to-pointer conversion for
> incomplete types is as bad as disallowing such references themselves.

I see three main uses for incomplete types, the first two related to
information hiding, and the third to dependencies

1) The incomplete type is a private implementation class within a
client-visible class. The client never has access to objects of this type,
or pointers and references to such objects, and all the code that uses it
(other than in function signatures) is contained within the library. In this
case, the choice of pointer or reference is arbitrary, since all the code
that uses the object has it being a complete type.

2) The incomplete type is client-visible, and a pointer or reference to such
a class is passed round as a handle. e.g. FILE* for the C file-handling
calls. I can't think of a good reason for using a reference in this case -
it is essentially just an immutable pointer, and you can't even take its
address. IMHO, all of these cases should use pointers for their handle
types, or define a small wrapper class that contains a pointer, and pass
that round as a handle. After all, the client cannot do any operations on
the object pointed-to or referred-to, only pass the handle back to the
original library, and using references just limits your choices - you can't
even rebind the same handle object to a new handle obtained from the
library.

3) The incomplete type is part of your code (either application or library),
but the current module only needs pointers or references to the objects, not
the details of them. This limits the dependencies of the current module - it
is not dependent on changes that affect the structure of the incomplete
type. This is the tricky case, and IMHO you should only use pointers for
this case, too, as you cannot safely convert references into pointers, as
the operation depends on the class definition.

> > >    If you let me express my own opinion, then after
> > >
> > > class Incomplete;
> > > Incomplete*    p = ...;
> > > Incomplete&    r = *p;
> > >
> > > &r should evaluates back to the value of p (i.e. &r == p).
> >         IMHO no, because it's too dangerous. Probably, you have a _very_
good
> > reason if you've defined operator&(). So, am I allowed to ignore it?!
>
>    Why of course you are! The reasons might be very serious. But if '&'
> is applied to an incomplete type reference its intention is likely to
> take object's address, not to call any object-defined operator.

That may be the intention, but if someone adds a #include for a header file
that completes the type, the code will now behave differently, even though
none of the types in the program have changed. Also, if the incomplete type
_does not_ contain an overload of operator&, this is defined behaviour, but
if the implementor of Incomplete defines operator&, the program silently
exhibits undefined behaviour.

This is a very good reason, IMHO, to make it illegal to take the address of
an object of incomplete type in all cases. It is for similar reasons that I
think it should be illegal to delete an object of incomplete type -
currently it is defined behaviour if the type has a trivial destructor, and
undefined otherwise.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optoelectronics
The opinions expressed in this message are not necessarily those of my
employer



---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Thu, 28 Jun 2001 15:28:48 GMT
Raw View
Eugene Karpachov wrote:
>=20
> Wed, 27 Jun 2001 19:36:42 GMT Igor A. Goussarov =CE=C1=D0=C9=D3=C1=CC:
>
> >[...] So if one has obtained a RIT as hanlde he cannot use it to call
> >functions that are designed to take PIT. [...]
>=20
> You can't use it anyway because type is incomplete and you don't know i=
f you
> can take *real* address from this reference.

   Surely I can't use it. And I am not going to use the object in any
way. Look, incomplete types are very good for creating handles. I mean
that in some programs it is necessary to give some kind of handle of a
core object to the client programmer, but ensure that the said CP can do
nothing to this object apart from passing its handle to other core
routines (like FILE* operations).
   The best way to achieve this is to leave the type incomplete in the
CP's code. Then the CP can obtain, store and pass pointers/references to
this incomplete type whitout any risk that he can do something undesired
to the object. See also 'pimpl' technique.
   What about taking real address... Why not? A reference can be bound
to an lvalue of (*p). Since objects are stored in the memory and the
reference represent an object, I'm pretty sure that the reference is
able to 'tell' the address of the object it is refered to.

> >   My point is: if some class was intentionally left incomplete and th=
e
> >pointers/references to it are used, then aforementioned pointers shoul=
d
> >remain invariant as long as the client code does not know about the
> >complete type and thus can only pass these pointers to some other
> >functions or convert them to/from references. Whatever good reason one
>=20
> So code semantics will change depending from some header inclusion?
> Not a good idea IMHO.

   I'd like to highlight the word 'intentionally'.
   If the incomplete class is used for purposes of a handle or a pimpl,
then its definition is perfectly hidden from the CP and there's no risk
that he can #include the definition somehow. If you are talking about
forgetting to include the proper header then it is 1) programmer's
fault, not a language's one 2) it's not common to have a translation
unit where some object exists solely to take its address :-))) more
likely some of its methods are called, thus a missing header can be
detected based on diagnostic messages from the compiler.

Igor

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Thu, 28 Jun 2001 18:09:36 GMT
Raw View
Anthony Williams wrote:
>
> 2) The incomplete type is client-visible, and a pointer or reference to such
> a class is passed round as a handle. e.g. FILE* for the C file-handling
> calls. I can't think of a good reason for using a reference in this case -
> it is essentially just an immutable pointer, and you can't even take its
> address. IMHO, all of these cases should use pointers for their handle
> types, or define a small wrapper class that contains a pointer, and pass
> that round as a handle. After all, the client cannot do any operations on
> the object pointed-to or referred-to, only pass the handle back to the
> original library, and using references just limits your choices - you can't
> even rebind the same handle object to a new handle obtained from the
> library.

   Usage of incomplete type as a handle is actually the first example I
kept in mind while writing to this thread.
   The pimpl idiom you have described as the first usage is also
important. But as you have noticed pimpl classes are complete within the
code that uses them, therefore no problem can arise.

   As for the handles: There are cases when you want to rebind a handle
to another value and there are cases when this is deprecated. Web server
plugin hardly have to know the type of the socket object, but it is
definitely important to indicate that this socket is not NULL and that
it is not going to change during the lifetime of a request processing
object - reference is definitely better here.
   So I'd say that here the choice between pointer and reference is also
arbitrary. The one that fits the model better is used.

> 3) The incomplete type is part of your code (either application or library),
> but the current module only needs pointers or references to the objects, not
> the details of them. This limits the dependencies of the current module - it
> is not dependent on changes that affect the structure of the incomplete
> type. This is the tricky case, and IMHO you should only use pointers for
> this case, too, as you cannot safely convert references into pointers, as
> the operation depends on the class definition.

   After all I have read and write to this thread, I tend to agree with
the OP's second message: the evil is not in the operations on incomplete
types but in ability to overload operator&().
   I admit, I have never find myself wanting to overload it. And
everybody contributing to this thread keep talking of "probably a very
good reason". The possible reason (as I can see) is just a convenience
of usage of smart pointers and memory handlers. Is there any other use
for them that I am missing?

> > > >    If you let me express my own opinion, then after
> > > >
> > > > class Incomplete;
> > > > Incomplete*    p = ...;
> > > > Incomplete&    r = *p;
> > > >
> > > > &r should evaluates back to the value of p (i.e. &r == p).
> > >         IMHO no, because it's too dangerous. Probably, you have a _very_
> good
> > > reason if you've defined operator&(). So, am I allowed to ignore it?!
> >
> >    Why of course you are! The reasons might be very serious. But if '&'
> > is applied to an incomplete type reference its intention is likely to
> > take object's address, not to call any object-defined operator.
>
> That may be the intention, but if someone adds a #include for a header file
> that completes the type, the code will now behave differently, even though
> none of the types in the program have changed. Also, if the incomplete type
> _does not_ contain an overload of operator&, this is defined behaviour, but
> if the implementor of Incomplete defines operator&, the program silently
> exhibits undefined behaviour.
>
> This is a very good reason, IMHO, to make it illegal to take the address of
> an object of incomplete type in all cases.

   I still believe that two ways (references and pointers) to store
handles of incomplete type without ability to convert from one form to
another will cause more troubles then solve problems.

> It is for similar reasons that I
> think it should be illegal to delete an object of incomplete type -
> currently it is defined behaviour if the type has a trivial destructor, and
> undefined otherwise.

   Deletion of any object of incomplete type is currently an undefined
behavior. I believe this topic was addressed a lot of times, but
nevertheless it is still an undefined behavior, not a compile-time
error... :(

Igor

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Fri, 29 Jun 2001 18:58:10 GMT
Raw View
"Igor A. Goussarov" <igusarov@akella.com> wrote in message
news:3B3B5F37.CC80FA5D@akella.com...
> Anthony Williams wrote:
> >
> > 2) The incomplete type is client-visible, and a pointer or reference to
such
> > a class is passed round as a handle. e.g. FILE* for the C file-handling
> > calls. I can't think of a good reason for using a reference in this
case -
> > it is essentially just an immutable pointer, and you can't even take its
> > address. IMHO, all of these cases should use pointers for their handle
> > types, or define a small wrapper class that contains a pointer, and pass
> > that round as a handle. After all, the client cannot do any operations
on
> > the object pointed-to or referred-to, only pass the handle back to the
> > original library, and using references just limits your choices - you
can't
> > even rebind the same handle object to a new handle obtained from the
> > library.
>
>    Usage of incomplete type as a handle is actually the first example I
> kept in mind while writing to this thread.
>    The pimpl idiom you have described as the first usage is also
> important. But as you have noticed pimpl classes are complete within the
> code that uses them, therefore no problem can arise.

Just to recap - I therefore think that it is the only case in which it makes
sense to use a reference to an incomplete type.

>    As for the handles: There are cases when you want to rebind a handle
> to another value and there are cases when this is deprecated. Web server
> plugin hardly have to know the type of the socket object, but it is
> definitely important to indicate that this socket is not NULL and that
> it is not going to change during the lifetime of a request processing
> object - reference is definitely better here.
>    So I'd say that here the choice between pointer and reference is also
> arbitrary. The one that fits the model better is used.

A pointer passed by value can never change in the lifetime of the request,
and it is simple to check a pointer for being NULL. If the non-NULL-ness is
a "hard" requirement, then I would use a smart pointer that guarantees it.
Obviously, it would have to be a smart pointer that can handle incomplete
types - a variant on my "GenericPtr", or Alan Griffiths' "grin_ptr".

> > 3) The incomplete type is part of your code (either application or
library),
> > but the current module only needs pointers or references to the objects,
not
> > the details of them. This limits the dependencies of the current
module - it
> > is not dependent on changes that affect the structure of the incomplete
> > type. This is the tricky case, and IMHO you should only use pointers for
> > this case, too, as you cannot safely convert references into pointers,
as
> > the operation depends on the class definition.
>
>    After all I have read and write to this thread, I tend to agree with
> the OP's second message: the evil is not in the operations on incomplete
> types but in ability to overload operator&().

I can't think of a sensible use where it is good design to overload
operator&(), provided you are responsible for the whole system. If you have
to use third-party tools or libraries, it may be a necessary evil, in order
to avoid breaking the design in other ways. I expand on one such example
below. Another is COM on Win32 - the standard Microsoft _com_ptr_t COM-aware
smart pointer template provides "operator&" to expose the underlying COM
interface pointer, to permit their usage to capture output parameters of COM
method calls, as if they were raw pointers. I do wonder if they could have
thought of a better way of doing it, given that they designed the whole COM
system, but we are stuck with that whilst we use Microsoft stuff.

>    I admit, I have never find myself wanting to overload it. And
> everybody contributing to this thread keep talking of "probably a very
> good reason". The possible reason (as I can see) is just a convenience
> of usage of smart pointers and memory handlers. Is there any other use
> for them that I am missing?

The only time I have ever found the need to overload operator&() is when
working with PRO*C, the Oracle Embedded SQL precompiler. When doing
multithreaded code, you need a sql_context handle, which I wanted to embed
in a class (to handle connection, automatic disconnection, etc.). In order
to seamlessly use this class in place of the original sql_context objects,
it is necessary to define operator&() to return a sql_context*, otherwise
the generated code will barf. The alternative is to explicitly extract the
sql_context from the containing class prior to each Embedded SQL operation -
messy and likely to cause bugs. In this situation, I then provided an
alternative method - addressOf() - to obtain the address of the class
object. I wasn't happy with this, but it seemed the best workaround - no
client code should explicitly be taking the address of the wrapper class
object anyway in this situation.

> > > > >    If you let me express my own opinion, then after
> > > > >
> > > > > class Incomplete;
> > > > > Incomplete*    p = ...;
> > > > > Incomplete&    r = *p;
> > > > >
> > > > > &r should evaluates back to the value of p (i.e. &r == p).
> > > >         IMHO no, because it's too dangerous. Probably, you have a
_very_
> > good
> > > > reason if you've defined operator&(). So, am I allowed to ignore
it?!
> > >
> > >    Why of course you are! The reasons might be very serious. But if
'&'
> > > is applied to an incomplete type reference its intention is likely to
> > > take object's address, not to call any object-defined operator.
> >
> > That may be the intention, but if someone adds a #include for a header
file
> > that completes the type, the code will now behave differently, even
though
> > none of the types in the program have changed. Also, if the incomplete
type
> > _does not_ contain an overload of operator&, this is defined behaviour,
but
> > if the implementor of Incomplete defines operator&, the program silently
> > exhibits undefined behaviour.
> >
> > This is a very good reason, IMHO, to make it illegal to take the address
of
> > an object of incomplete type in all cases.
>
>    I still believe that two ways (references and pointers) to store
> handles of incomplete type without ability to convert from one form to
> another will cause more troubles then solve problems.

Design/Coding problems, yes. If we make it illegal (compile-time error) to
take the address of a reference to an incomplete type, then there are
circumstances in which you will hit the problem that you have a reference,
and you need a pointer. In this case, you will have to think of a new way of
getting a pointer, or how to drop the need for such a pointer. I would
suggest always using pointers (or smart pointers), but that is my opinion.
However, the upshot of making it illegal is that you can never silently
introduce the undefined behaviour you can today - you compile your code
today and it works. Someone changes another module, and you relink. Now
_your_ module exhibits undefined behaviour. Yuck.

> > It is for similar reasons that I
> > think it should be illegal to delete an object of incomplete type -
> > currently it is defined behaviour if the type has a trivial destructor,
and
> > undefined otherwise.
>
>    Deletion of any object of incomplete type is currently an undefined
> behavior. I believe this topic was addressed a lot of times, but
> nevertheless it is still an undefined behavior, not a compile-time
> error... :(

5.3.5p5:
"If the object being deleted has incomplete class type at the point of
deletion and the complete class has a nontrivial destructor or a
deallocation function, the behavior is undefined."

I read that as having the corollary that if the complete class has a trivial
destructor, then the behaviour _is_ defined, unless one of the other reasons
for it being undefined applies. I think it should be a compile-time error in
all cases.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optoelectronics
The opinions expressed in this message are not necessarily those of my
employer



---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Sergey P. Derevyago" <non-existent@iobox.com>
Date: Mon, 25 Jun 2001 15:12:41 GMT
Raw View
"Igor A. Goussarov" wrote:
> >         IMHO we should eliminate the reason of this "undefined behavior".
>    How? At the point where &x is encountered and type of x is incomplete
> it is hard to say whether the complete class will have an operator& or
> not.
 Yes :)

> The possible ways are:
> 1. Disallow taking address of references to objects of incomplete type.
 This one. And not only...

> 2. Disallow references to objects of incomplete type themselves.
 A very bad idea :)

>    What exactly are you after?
>    To me 2) seems to be way too heavy weapon for this bug, 1) seems to
> affect the symmetry of taking address - dereference operations.
 IMHO this symmetry should not be taken into account. You can't do anything
"interesting" with reference if you don't know exactly what the object
really is. In principle, references emulate objects.

>    If you let me express my own opinion, then after
>
> class Incomplete;
> Incomplete*    p = ...;
> Incomplete&    r = *p;
>
> &r should evaluates back to the value of p (i.e. &r == p).
 IMHO no, because it's too dangerous. Probably, you have a _very_ good
reason if you've defined operator&(). So, am I allowed to ignore it?!

 [snip]

> P.S.
>    I believe that taking address of a variable of type 'reference to
> incomplete type' is not the only problem you may encounter. Expressions
> like
>
> class Incomplete;
> Incomplete*       p = ...;
> Incomplete*       q = &*p;
>
> are also rather suspicious...
 Yes, thank you. This should also be deprecated, IMHO :)
--
         With all respect, Sergey.          http://cpp3.virtualave.net/
         mailto : ders at skeptik.net

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Sergey P. Derevyago" <non-existent@iobox.com>
Date: Wed, 20 Jun 2001 19:07:00 GMT
Raw View
"Igor A. Goussarov" wrote:
> > AFAIK the following code is perfectly legal:
> > -----------------------------------8<-----------------------------------
> > struct X;
> >
> > X* f(X& x) { return &x; }
> > -----------------------------------8<-----------------------------------
> > And it "perfectly" ignores any possible X::operator&().
>
>    If it has one then according to 5.3.1:4 it is undefined behavior.
>
 IMHO we should eliminate the reason of this "undefined behavior".

> > Are there any good reasons to allow to take an address of a reference to an
> > object of an incomplete type?
>
>    Generally it is good to have an ability to operate with pointers to
> incomplete types.
 Surely yes. But references is not pointers.

> Since references to incomplete types are allowed and
> there's a way of binding a reference to the object pointed to by a given
> pointer (both of them to the same incomplete type) then there should be
> the way of doing reverse thing: obtain a pointer from a given reference.
 IMHO this "reverse thing" is unjustified dangerous.
--
         With all respect, Sergey.          http://cpp3.virtualave.net/
         mailto : ders at skeptik.net

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Thu, 21 Jun 2001 17:30:31 GMT
Raw View
"Sergey P. Derevyago" wrote:
>
> "Igor A. Goussarov" wrote:
> > > AFAIK the following code is perfectly legal:
> > > -----------------------------------8<-----------------------------------
> > > struct X;
> > >
> > > X* f(X& x) { return &x; }
> > > -----------------------------------8<-----------------------------------
> > > And it "perfectly" ignores any possible X::operator&().
> >
> >    If it has one then according to 5.3.1:4 it is undefined behavior.
> >
>         IMHO we should eliminate the reason of this "undefined behavior".

   How? At the point where &x is encountered and type of x is incomplete
it is hard to say whether the complete class will have an operator& or
not. The possible ways are:
1. Disallow taking address of references to objects of incomplete type.
2. Disallow references to objects of incomplete type themselves.

   What exactly are you after?
   To me 2) seems to be way too heavy weapon for this bug, 1) seems to
affect the symmetry of taking address - dereference operations.

   If you let me express my own opinion, then after

class Incomplete;
Incomplete*    p = ...;
Incomplete&    r = *p;

&r should evaluates back to the value of p (i.e. &r == p).

   This allows free conversion between pointers and references to an
incomplete types and it is fine as long as the object itself is not
used.
   There's no reason asking &r to involve a possible operator&. This
type can remain incomplete through all the program (e.g. a plugin for
the server and this incomplete type serves as a handle to some server
object that the plugin should not use directly).

   Since the point of actual code generation is not specified and this
type might have been completed later in the same translation unit, it
cannot be predicted, whether the compiler knows about existence of
operator& the moment it generates the code for the function in question
or not. Hence undefined behavior of the program. And probably no way of
turning this behavior into a definite one. Again, banning something
doesn't sound very attractive (IMHO).

Igor

P.S.
   I believe that taking address of a variable of type 'reference to
incomplete type' is not the only problem you may encounter. Expressions
like

class Incomplete;
Incomplete*       p = ...;
Incomplete*       q = &*p;

are also rather suspicious...

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Sergey P. Derevyago" <non-existent@iobox.com>
Date: Mon, 18 Jun 2001 04:25:18 GMT
Raw View
AFAIK the following code is perfectly legal:
-----------------------------------8<-----------------------------------
struct X;

X* f(X& x) { return &x; }
-----------------------------------8<-----------------------------------
And it "perfectly" ignores any possible X::operator&().

Are there any good reasons to allow to take an address of a reference to an
object of an incomplete type?
--
         With all respect, Sergey.          http://cpp3.virtualave.net/
         mailto : ders at skeptik.net

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Igor A. Goussarov" <igusarov@akella.com>
Date: Mon, 18 Jun 2001 13:30:44 GMT
Raw View
"Sergey P. Derevyago" wrote:
>
> AFAIK the following code is perfectly legal:
> -----------------------------------8<-----------------------------------
> struct X;
>
> X* f(X& x) { return &x; }
> -----------------------------------8<-----------------------------------
> And it "perfectly" ignores any possible X::operator&().

   If it has one then according to 5.3.1:4 it is undefined behavior.

> Are there any good reasons to allow to take an address of a reference to an
> object of an incomplete type?

   Generally it is good to have an ability to operate with pointers to
incomplete types. Since references to incomplete types are allowed and
there's a way of binding a reference to the object pointed to by a given
pointer (both of them to the same incomplete type) then there should be
the way of doing reverse thing: obtain a pointer from a given reference.

Igor

---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: "Anthony Williams" <anthwil@nortelnetworks.com>
Date: Mon, 18 Jun 2001 13:32:35 GMT
Raw View
"Sergey P. Derevyago" <non-existent@iobox.com> wrote in message
news:3B2CDC2A.7959DB7D@iobox.com...
> AFAIK the following code is perfectly legal:
> -----------------------------------8<-----------------------------------
> struct X;
>
> X* f(X& x) { return &x; }
> -----------------------------------8<-----------------------------------
> And it "perfectly" ignores any possible X::operator&().
>
> Are there any good reasons to allow to take an address of a reference to
an
> object of an incomplete type?

5.3.1p4:

"The address of an object of incomplete type can be taken, but if the
complete type of that object is a class type that declares operator&() as a
member function, then the behavior is undefined (and no diagnostic is
required)."

So your example code is undefined behaviour if there is a user-provided
X::operator&(), and defined if there is not.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optoelectronics
The opinions expressed in this message are not necessarily those of my
employer



---
[ 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.research.att.com/~austern/csc/faq.html                ]





Author: iltchenko@yahoo.com (Andrei Iltchenko)
Date: Mon, 18 Jun 2001 23:55:07 GMT
Raw View
"Sergey P. Derevyago" <non-existent@iobox.com> wrote in message news:<3B2CDC2A.7959DB7D@iobox.com>...

> AFAIK the following code is perfectly legal:
> -----------------------------------8<-----------------------------------
> struct X;
>
> X* f(X& x) { return &x; }
> -----------------------------------8<-----------------------------------
> And it "perfectly" ignores any possible X::operator&().
>
> Are there any good reasons to allow to take an address of a reference to an
> object of an incomplete type?

Sorry to diappoint you, but in accordance with the Standard the piece
of code shown is a perfect example of undefined behaviour.

5.3.1/4 explicitly says that while it's possible to take address of an
object of an incomplete type, the behaviour is undefined should the
complete type of that object have a member function 'operator&'.


Regards,

Andrei Iltchenko.

---
[ 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.research.att.com/~austern/csc/faq.html                ]