Topic: pointer to member derivation question
Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 1999/06/29 Raw View
In article <377391F5.C8A41F3A@physik.tu-muenchen.de>,
Christopher Eltschka <celtschk@physik.tu-muenchen.de> wrote:
> Jim Hyslop wrote:
[snip]
> > void f()
> > {
> > Holder h;
> > Base Holder::* elt = &h._derived;
> > }
>
> No. &Holder::_derived gives a Derived Holder::*.
Right, thanks (and to Pete Becker) for pointing that out.
[snip]
[on the topic of reserved identifiers]
> However, the implementor of your compiler may have the
> same misunderstanding, and therefore it's a good idea to
> avoid them anyway.
I really do know the rules ;-), but I got a little lazy in my post. I
tend to avoid leading underscores anyway, for the reason you just
mentioned. I usually try to be more precise - sorry about that.
--
Jim
I ignore all email from recruitment agencies.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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: Jim Hyslop <jim.hyslop@leitch.com>
Date: 1999/06/25 Raw View
In article <vgvk8swxj97.fsf@ms.com>,
Colin Rafferty <craffert@ms.com> wrote:
> Hi-
>
> I have the following code, and it makes sense to me that it should
> work, but different compilers have different thoughts on the subject.
>
> class Base { /* ... */ };
>
> class Derived : public Base { /* ... */ };
>
> class Holder
> {
> public:
> Derived _derived;
> };
>
> void f()
> {
> Base Holder::* elt = &Holder::_derived;
> }
Er, I hate to point out the obvious, but doesn't elt require an *object*
to work on, i.e.:
void f()
{
Holder h;
Base Holder::* elt = &h._derived;
}
BTW, you should avoid using leading underscores in identifiers, since
they are reserved for compiler and STL usage.
--
Jim
I ignore all email from recruitment agencies.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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: 1999/06/25 Raw View
> But the original poster's question has to do with conversions of
> "Derived (T::*)(X1,X2) cv" to "Base (T::*)(X1,X2)". From previous
> discussion on this newsgroup, I gather two things: the conversion is
> forbidden, and there is no good reason to forbid it.
How does the base code know how to derferrence a pointer to the
insides of a derived class it knows nothing about?
---
[ 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: Pete Becker <petebecker@acm.org>
Date: 1999/06/26 Raw View
Jim Hyslop wrote:
>
> > void f()
> > {
> > Base Holder::* elt = &Holder::_derived;
> > }
> Er, I hate to point out the obvious, but doesn't elt require an *object*
> to work on, i.e.:
No, the code above is correct: elt is a pointer to member data, not an
ordinary pointer. There tends to be more discussion about pointers to
member functions, so the syntax for a pointer to member data looks
disarmingly simple. An ordinary pointer is even simpler:
Base * elt = &h._derived; // ordinary pointer
---
[ 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: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/06/26 Raw View
Jim Hyslop wrote:
>
> In article <vgvk8swxj97.fsf@ms.com>,
> Colin Rafferty <craffert@ms.com> wrote:
> > Hi-
> >
> > I have the following code, and it makes sense to me that it should
> > work, but different compilers have different thoughts on the subject.
> >
> > class Base { /* ... */ };
> >
> > class Derived : public Base { /* ... */ };
> >
> > class Holder
> > {
> > public:
> > Derived _derived;
> > };
> >
> > void f()
> > {
> > Base Holder::* elt = &Holder::_derived;
> > }
> Er, I hate to point out the obvious, but doesn't elt require an *object*
> to work on, i.e.:
>
> void f()
> {
> Holder h;
> Base Holder::* elt = &h._derived;
> }
No. &Holder::_derived gives a Derived Holder::*.
AFAIK your code wouldn't be legal at all, even if the obvious
conversion were allowed, since &h._derived is of type Derived*,]
not Derived Holder::*.
>
> BTW, you should avoid using leading underscores in identifiers, since
> they are reserved for compiler and STL usage.
While I agree with the "should", you are not completely right
here. Only identifiers using double underscores and identifiers
beginning with underscore and capital letter are reserved in
every scope; all other identifiers beginning with a single
underscore are only reserved in global scope and in namespace
std.
However, the implementor of your compiler may have the
same misunderstanding, and therefore it's a good idea to
avoid them anyway.
---
[ 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: 1999/06/26 Raw View
Ron Natalie wrote:
>
> > But the original poster's question has to do with conversions of
> > "Derived (T::*)(X1,X2) cv" to "Base (T::*)(X1,X2)". From previous
> > discussion on this newsgroup, I gather two things: the conversion is
> > forbidden, and there is no good reason to forbid it.
>
> How does the base code know how to derferrence a pointer to the
> insides of a derived class it knows nothing about?
It knows the complete signature of the member function. It should be
possible, I would think, to design an implementation of member function
pointers where that would be sufficient information.
---
[ 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: bill@gibbons.org (Bill Gibbons)
Date: 1999/06/23 Raw View
In article <vgvk8swxj97.fsf@ms.com>, Colin Rafferty <craffert@ms.com> wrote:
> I have the following code, and it makes sense to me that it should
> work, but different compilers have different thoughts on the subject.
>
> class Base { /* ... */ };
>
> class Derived : public Base { /* ... */ };
>
> class Holder
> {
> public:
> Derived _derived;
> };
>
> void f()
> {
> Base Holder::* elt = &Holder::_derived;
> }
>
> I don't have a copy of the standard, but the Dec 96 WP seems to say
> nothing about it in either [dcl.mptr] or [conv.mem].
Pointers to members can be converted implicitly from base to derived but
must be explicitly converted from derived to base (so the above code is
ill-formed). This is backwards from ordinary pointers.
The reason is type safety.
With ordinary pointers, you can't implicitly convert from base
to derived because there is no guarantee that the object itself is
actually a derived class object.
With pointers to members, you can't implicitly convert from derived
to base because there is no guarantee, when the pointer to member
is subsequently dereferenced with a pointer with static type
"pointer to base", that the object itself will actually be a derived
class object.
Since the dereference of the (converted) pointer to member contains
no type information to hint that there could be a problem (because
the PM and pointer both refer to the base class in their static type),
the potential problem must be caught at the time the pointer to member
is converted from derived to base.
-- Bill Gibbons
bill@gibbons.org
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Colin Rafferty <craffert@ms.com>
Date: 1999/06/23 Raw View
Bill Gibbons writes:
> In article <vgvk8swxj97.fsf@ms.com>, Colin Rafferty <craffert@ms.com> wrote:
>> I have the following code, and it makes sense to me that it should
>> work, but different compilers have different thoughts on the subject.
>>
>> class Base { /* ... */ };
>>
>> class Derived : public Base { /* ... */ };
>>
>> class Holder
>> {
>> public:
>> Derived _derived;
>> };
>>
>> void f()
>> {
>> Base Holder::* elt = &Holder::_derived;
>> }
>>
>> I don't have a copy of the standard, but the Dec 96 WP seems to say
>> nothing about it in either [dcl.mptr] or [conv.mem].
> Pointers to members can be converted implicitly from base to derived but
> must be explicitly converted from derived to base (so the above code is
> ill-formed). This is backwards from ordinary pointers.
I think you are thinking of the opposite thing that I am looking for.
I know that I cannot implicitly convert from `Object Derived::*' to
`Object Base::*'.
This would allow me to refer to a member in Base that is only in
Derived.
However, this is not what I am doing.
I want to convert from `Derived Object::*' to `Base Object::*'.
I would like to see a reference to the standard that says that this is
not allowed (or that it is allowed).
Thanks.
--
Colin
[ 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: Jim Hyslop <jim.hyslop@leitch.com>
Date: 1999/06/24 Raw View
In article <bill-2306990925210001@bgibbons.vip.best.com>,
bill@gibbons.org (Bill Gibbons) wrote:
>
> In article <vgvk8swxj97.fsf@ms.com>, Colin Rafferty <craffert@ms.com>
wrote:
>
> > I have the following code, and it makes sense to me that it should
> > work, but different compilers have different thoughts on the
subject.
> >
> > class Base { /* ... */ };
> >
> > class Derived : public Base { /* ... */ };
> >
> > class Holder
> > {
> > public:
> > Derived _derived;
> > };
> >
> > void f()
> > {
> > Base Holder::* elt = &Holder::_derived;
> > }
> >
> > I don't have a copy of the standard, but the Dec 96 WP seems to say
> > nothing about it in either [dcl.mptr] or [conv.mem].
>
> Pointers to members can be converted implicitly from base to derived
> but
> must be explicitly converted from derived to base
True, but it does not address the example shown. The original poster
does not attempt to convert from "T derived::*" to "T base::*" but from
"derived T::*" to "base T::*" - a subtle distinction. It seems not
significantly different to me than:
Holder h;
Base *bptr = &h._derived
--
Jim
I ignore all email from recruitment agencies.
Please do not send me email with questions - post
here.
Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.
---
[ 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: Colin Rafferty <craffert@ms.com>
Date: 1999/06/24 Raw View
Siemel Naran writes:
> On 23 Jun 99 01:25:27 GMT, Colin Rafferty <craffert@ms.com> wrote:
>> class Base { /* ... */ };
>>
>> class Derived : public Base { /* ... */ };
>>
>> class Holder
>> {
>> public:
>> Derived _derived;
>> };
>>
>> void f()
>> {
>> Base Holder::* elt = &Holder::_derived;
>> }
>>
>> I don't have a copy of the standard, but the Dec 96 WP seems to say
>> nothing about it in either [dcl.mptr] or [conv.mem].
> If I'm not mistaken, covariant types for pointer to members are not
> allowed. Of my two compilers, Comeau (an EDG compiler) does not
> allow it, whereas Egcs does.
I know that different compilers feel differently about this. However,
I would like to know what the standard says about this.
> Allowing covariant types is no problem, but the implementor has
> to be slighly more careful.
This is true.
Of course, the implementor only has to be careful, not supernatural.
--
Colin
---
[ 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: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/06/24 Raw View
On 23 Jun 1999 17:18:52 GMT, Bill Gibbons <bill@gibbons.org> wrote:
>In article <vgvk8swxj97.fsf@ms.com>, Colin Rafferty <craffert@ms.com> wrote:
>> class Holder
>> {
>> public:
>> Derived _derived;
>> };
>>
>> void f()
>> {
>> Base Holder::* elt = &Holder::_derived;
>> }
>Pointers to members can be converted implicitly from base to derived but
>must be explicitly converted from derived to base (so the above code is
>ill-formed). This is backwards from ordinary pointers.
This paragraph deals with conversions of "T (Base::*)(X1,X2) cv" to
"T (Derived::*)(X1,X2) cv". In short, if class Base contains a
function with signature "T (Base::*)(X1,X2) cv" then as class
Derived inherits everything in class Base, class Derived also has
a function with signature "T (Derived::*)(X1,X2) cv".
But the original poster's question has to do with conversions of
"Derived (T::*)(X1,X2) cv" to "Base (T::*)(X1,X2)". From previous
discussion on this newsgroup, I gather two things: the conversion is
forbidden, and there is no good reason to forbid it.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
[ 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: bill@gibbons.org (Bill Gibbons)
Date: 1999/06/24 Raw View
In article <vgvwvwuvaob.fsf@ms.com>, Colin Rafferty <craffert@ms.com> wrote:
> I want to convert from `Derived Object::*' to `Base Object::*'.
>
> I would like to see a reference to the standard that says that this is
> not allowed (or that it is allowed).
Oh, that part is easy.
The only implicit conversions between built-in types are the standard
conversions described in clause 4.
For pointers to members, this boils down to the first sentence of 4.11/1:
An rvalue of type "pointer to member of B of type cv T," where B is a
class type, can be converted to an rvalue of type "pointer to member
of D of type cv T," where D is a derived class (clause 10) of B.
in which the member type must be exactly the same; and the qualification
conversions in section 4.4, which do not apply to this case.
The only explicit conversions between built-in types are those described in
5.2.3 (function-style casts), 5.4 (old-style casts), 5.2.9 (static_cast),
5.2.10 (reinterpret_cast) and 5.2.11 (const_cast).
A static_cast or const_cast can change the qualification, but not the
underlying type, of the member type.
A reinterpret_cast can change the underlying member type, but the result
is not valid for any use except casting back to the original type.
Function-style and old-style casts are defined in terms of new-style casts.
As for whether base/derived conversions on the member type could have been
allowed, the answer is certainly yes - although conversions across virtual
derivation would not have been allowed, basically for the same reason
that such conversions are not allowed on the class portion of the PM type.
(Significant complexity and performance penalty for marginal utility.)
The reason that base/derived conversions on the member type were not added
was that there was no demand for them, and the language was already too
large. Had it been proposed it would have been rejected along with dozens
of other extension proposals unless someone demonstrated significant need
for the feature.
-- Bill Gibbons
bill@gibbons.org
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Colin Rafferty <craffert@ms.com>
Date: 1999/06/23 Raw View
Hi-
I have the following code, and it makes sense to me that it should
work, but different compilers have different thoughts on the subject.
class Base { /* ... */ };
class Derived : public Base { /* ... */ };
class Holder
{
public:
Derived _derived;
};
void f()
{
Base Holder::* elt = &Holder::_derived;
}
I don't have a copy of the standard, but the Dec 96 WP seems to say
nothing about it in either [dcl.mptr] or [conv.mem].
Thanks.
--
Colin
---
[ 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: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/06/23 Raw View
On 23 Jun 99 01:25:27 GMT, Colin Rafferty <craffert@ms.com> wrote:
> class Base { /* ... */ };
>
> class Derived : public Base { /* ... */ };
>
> class Holder
> {
> public:
> Derived _derived;
> };
>
> void f()
> {
> Base Holder::* elt = &Holder::_derived;
> }
>
>I don't have a copy of the standard, but the Dec 96 WP seems to say
>nothing about it in either [dcl.mptr] or [conv.mem].
If I'm not mistaken, covariant types for pointer to members are not
allowed. Of my two compilers, Comeau (an EDG compiler) does not
allow it, whereas Egcs does.
Allowing covariant types is no problem, but the implementor has
to be slighly more careful. Consider
struct A { int a; };
struct B : A { int b; };
struct C : B { int c; };
struct Holder { C c1,c2; };
void f2() { B Holder::*const elt=&Holder::c2; }
The entity "&Holder::c2" means the address of the C part of the
c2 of a Holder object. Assuming sizeof(int) is 4, then sizeof(A)
is 4, sizeof(B) is 8, sizeof(C) is 12. Now suppose that the
implementation arranges a C object so that the C-only part is
first, the B-only part is next, the A-only part is next (most
implementations put the A part first, then B, then C). Then
"&Holder::c2" would be 12 -- meaning go 12 bytes from the start
of the Holder object to get to the C part of c2. But the full
expression "B Holder::*const elt=&Holder::c2" changes the
meaning of the offset. Now we must get to the BA part of c2,
which means that the offset is 16.
--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
[ 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 ]