From -3696835693410363120
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,4b5b1798bd044336,start
X-Google-Attributes: gidf78e5,public
From: JdeBP@jba.co.uk (Jonathan de Boyne Pollard)
Subject: Re: pointer to member conversion
Date: 1996/04/26
Message-ID: <4lr7um$q7r@silver.jba.co.uk>#1/1
X-Deja-AN: 151589134
x-lines: 53
references: <3180E8D7.4352@stratus.com>
content-length: 2188
organization: JBA Software Products, Studley, England.
reply-to: JdeBP@donor2.demon.co.uk
newsgroups: comp.std.c++
originator: clamage@taumet


Vladimir Neyman (Vladimir_Neyman@stratus.com) wrote:
| class A {};
|
| class B : public A {};
|
| struct C {
|  B m_b;
| }
|
| A C::*p = &C::m_b;
|
| The last assignement produces a compiler error in MVC:
| "cannot convert from 'class B C::*' to 'class A C::*'".
|
| At first, I thought it is a bug in MVC because a pointer to
| a derived class should be convertable to a pointer to a
| base class.
|
| But then I looked into standard draft and found ($4.11) that for 
| pointers to members, onthe opposite, a pointer to a base class is 
| convertable to a pointer to a derived class. The standard says that 
| this inversion of normal rules  is necessary for type safety.

What the standard is actually says is that "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 of B".

Substituting for your example, "a pointer to member of `C' of type A"
is convertible to "a pointer to member of `D' of type A", assuming a class 
D derived from C (which is not in your example).

The rationale of allowing "Base::*" to be converted to "Derived::*" is, of
course, that all of the members of "Base" are also members of "Derived", so
the conversion is safe, whereas the converse is not true.

What you are trying to do, however, is convert from "a pointer to member 
of `C' of type B" to "a pointer to member of `C' of type A".  In my
slightly out of date copy of the WP (Steve Rumsby where are you?), at
least, there is *no* pointer-to-member conversion that allows that.

I would guess that the reasoning behind this is that pointers to members
are *not* pointers to objects.  Whereas "B *" is a pointer to an object 
and can be converted to "A *", a "B C::*" is a pointer to a *member*, and
you need to supply an object of type `C' before you can get an object of
type `B' out of it, let alone a "B *".  For example :

	B C::* ptr_m_b = &C::m_b ; // pointer to member of class C, type B
	C c ;			   // object of class C
	A * ptr_a = &c.*ptr_m_b ;  // Convert "B *" to "A *"

I'm as surprised as you are that Microsoft C++ appears to have got it right
for once.


[ 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                             ]



