Topic: Pointer to Member Fun


Author: "Jeremy Furtek" <jeremyf@believe.com>
Date: 15 Nov 00 02:05:23 GMT
Raw View
Is there a (standard) acceptable conversion from (pointer-to-member of A of
type D) to (pointer-to-member of A of type B), where D is derived from B?

The ISO Standard seems to explicitly discuss conversions for
pointers-to-members of classes derived from A (in the terminology of the
example above) in "Sec 5.2.9 : static_cast" and "4.11 : Pointer to member
conversions." I haven't been able to find any mention of this specific
variation, where the member types differ. (Please see end of post for sample
code.)

Is there something inherently ambiguous about this operation that prevents
it from being legal?

The code below was tested with MSVC6, gcc 2.95.2, and Comeau C++.  See
inline comments for specific compiler error messages.

----------------------------------------------------------------------
#include <stdio.h>

struct MBase {
 int i;
};

struct MDerived : public MBase {
 int j;
};

struct A {
 MDerived d;
};

typedef MDerived A::* A_MDerived;
typedef MBase A::* A_MBase;

int main(int argc, char* argv[])
{
 A_MDerived amd = &A::d;
 /////////////////////////////////////////////////
 // Following line works with gcc 2.95.2
 A_MBase amb = &A::d;
 /////////////////////////////////////////////////
 // Following line does not work with any of the compilers
 A_MBase amb2 = static_cast<A_MBase>(&A::d);
 /////////////////////////////////////////////////
 // Following line only version that works under MSVC6
 // and Comeau C++
 A_MBase amb3 = reinterpret_cast<A_MBase>(&A::d);
 /////////////////////////////////////////////////
 printf("Execution completed\n");
 return 0;
}
----------------------------------------------------------------------





      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]

[ 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: "David Abrahams" <abrahams@mediaone.net>
Date: 2000/11/15
Raw View
The standard conversion for pointers-to-members goes in an unintuitive (at
first) direction.

  R (Base::*)(<args>) -> R (Derived::*)(<args>)

The conversion you're asking for

  R (Derived::*)(<args>) -> R (Base::*)(<args>)

isn't safe because of course, the base class may not contain the derived
class member.

"Jeremy Furtek" <jeremyf@believe.com> wrote in message
news:8us9hr$26kq3$1@ID-39279.news.dfncis.de...
> Is there a (standard) acceptable conversion from (pointer-to-member of A
of
> type D) to (pointer-to-member of A of type B), where D is derived from B?





---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: "Jeremy Furtek" <jeremyf@believe.com>
Date: 2000/11/15
Raw View
I wholeheartedly agree about the unintuitive nature of the direction. I had
to read the relevant parts of the spec a few times to understand the
behavior that you are alluding to.

I am not referring to this, however. (Perhaps my original post was unclear.)
I want the __member__ types to exhibit an inheritance relationship, not the
containing class. In other words,

class Base {}
class Derived : public Base {}

class Container {
    Derived d;
}

Ther would be no problem with obtaining a (Base*) from a (Derived*), since
Derived is derived from Base.

Derived g_d;
Derived* pd = &g_d;
Base* pBase = pd;

However, when the Derived object is accessed via a pointer-to-member, the
conversion seems undefined or inconsistently defined (see original post):

Derived Container::* pmd = &(Container::d);  // This works fine
Base Container::* pmb = pmd; // Doesn't work.....why not?


Jeremy Furtek
jeremyf@believe.com


"David Abrahams" <abrahams@mediaone.net> wrote in message
news:007201c04f11$4eed0b50$0500a8c0@dragonsys.com...
> The standard conversion for pointers-to-members goes in an unintuitive (at
> first) direction.
>
>   R (Base::*)(<args>) -> R (Derived::*)(<args>)
>
> The conversion you're asking for
>
>   R (Derived::*)(<args>) -> R (Base::*)(<args>)
>
> isn't safe because of course, the base class may not contain the derived
> class member.
>
> "Jeremy Furtek" <jeremyf@believe.com> wrote in message
> news:8us9hr$26kq3$1@ID-39279.news.dfncis.de...
> > Is there a (standard) acceptable conversion from (pointer-to-member of A
> of
> > type D) to (pointer-to-member of A of type B), where D is derived from
B?
>
>
>
>
>
> ---
> [ 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                ]
> [ Note that the FAQ URL has changed!  Please update your bookmarks.     ]
>


---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: rjpeters@goethe.klab.caltech.edu (Robert J. Peters)
Date: 2000/11/16
Raw View
> "Jeremy Furtek" <jeremyf@believe.com> wrote
> > Is there a (standard) acceptable conversion from (pointer-to-member of A
> of
> > type D) to (pointer-to-member of A of type B), where D is derived from B?

"David Abrahams" <abrahams@mediaone.net> replied:
> The standard conversion for pointers-to-members goes in an unintuitive (at
> first) direction.
>
>   R (Base::*)(<args>) -> R (Derived::*)(<args>)
>
> The conversion you're asking for
>
>   R (Derived::*)(<args>) -> R (Base::*)(<args>)
>
> isn't safe because of course, the base class may not contain the derived
> class member.

Actually, I think this may be a misinterpretation of the original
question. I raised this same question a couple months back on
c.l.c++.m (see
http://www.deja.com/viewthread.xp?AN=673210964&group=comp.lang.c%2B%2B.moderated),
and most people originally (mis)interpreted it in the same way. My
question was, whether the following conversion is acceptable

  (1)    Derived A::*  --->  Base A::*

given that Base is an accessible, non-virtual base class for Derived.

The answer is that this conversion (1) is not specifically allowed by the
standard, and therefore it is not valid. The only pointer to member
conversion that is explicitly allowed is this:

  (2)    T Base::*  ---> T Derived::*


My view is that conversion (1) should be allowed by the standard. I
think the conversion is implementable, and that it would be a useful
addition to the language. There are some technicalities in
implementing this relating to multiple inheritance, but I don't think
these are any more difficult than the issues involved in converting a
Derived* to Base* when multiple inheritance is involved (i.e., we need
some extra math to account for address offsets if Base is not the
first base class in Derived's base class list).

There was one person (Ron Hunsinger, I think) who agreed with me in
the previous discussion... I'd still be interested to see if others
think that (1) could be practical and useful. If so, I'd consider
writing up a defect report.

Cheers,
Rob Peters


--
****************************************************************
Robert J. Peters                  Computation and Neural Systems
rjpeters@klab.caltech.edu                                Caltech
www.klab.caltech.edu/rjpeters/                  Mail Code 139-74
(626) 395-2882                                Pasadena, CA 91106

---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: "Jeremy Furtek" <jeremyf@believe.com>
Date: 2000/11/17
Raw View
Thanks for the archive link - I should have searched harder.

My intended usage for the conversion was similar to yours, and, IMHO, valid
and useful.

I checked the list of C++ Standard Active Issues at
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html and didn't find
anything related specifically to this matter.

Given the newsgroup "silence" (I posted in comp.lang.c++.moderated as well
without any response), I am not sure what the general opinion on the
practicality and usefulness of this is.

I also wonder if this constitutes an {error, inconsistency, ambiguity,
omission} and thus a Defect Report, as opposed to an addition to the
language?

Jeremy Furtek
mailto:jeremyf@believe.com

"Robert J. Peters" <rjpeters@goethe.klab.caltech.edu> wrote in message
news:6gy9yj4usc.fsf@goethe.klab.caltech.edu...
> Actually, I think this may be a misinterpretation of the original
> question. I raised this same question a couple months back on
> c.l.c++.m (see
>
http://www.deja.com/viewthread.xp?AN=673210964&group=comp.lang.c%2B%2B.moder
ated),
> and most people originally (mis)interpreted it in the same way.
(snip)
>
> There was one person (Ron Hunsinger, I think) who agreed with me in
> the previous discussion... I'd still be interested to see if others
> think that (1) could be practical and useful. If so, I'd consider
> writing up a defect report.
>
> Cheers,
> Rob Peters
>
>
> --
> ****************************************************************
> Robert J. Peters                  Computation and Neural Systems
> rjpeters@klab.caltech.edu                                Caltech
> www.klab.caltech.edu/rjpeters/                  Mail Code 139-74
> (626) 395-2882                                Pasadena, CA 91106



---
[ 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                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]






Author: bill@gibbons.org (Bill Gibbons)
Date: Sun, 19 Nov 2000 00:48:34 GMT
Raw View
In article <8uuf4l$2v28s$1@ID-39279.news.dfncis.de>, "Jeremy Furtek"
<jeremyf@believe.com> wrote:

> I want the __member__ types to exhibit an inheritance relationship, not the
> containing class. In other words,
>
> class Base {}
> class Derived : public Base {}
>
> class Container {
>     Derived d;
> }
>
> Ther would be no problem with obtaining a (Base*) from a (Derived*), since
> Derived is derived from Base.
>
> Derived g_d;
> Derived* pd = &g_d;
> Base* pBase = pd;
>
> However, when the Derived object is accessed via a pointer-to-member, the
> conversion seems undefined or inconsistently defined (see original post):
>
> Derived Container::* pmd = &(Container::d);  // This works fine
> Base Container::* pmb = pmd; // Doesn't work.....why not?

There is no real reason for this restriction except the general rule that
the language shouldn't be made more complex without a compelling reason.

Prior to about 1997 it was possible to do a PM cast where the classes
containing the members were related by virtual inheritance.  This was quite
complex to implement correctly.  (One compiler actually synthesized functions
containing switch statements to assist performing the cast.)  Allowing casts
where the member types were pointers related by virtual inheritance would
have been a nightmare.

But once PM casts were restricted not to involve virtual inheritance, it
would have been reasonable to place the same restriction on casts between
data member types within pointers to members.  This would make such casts
trivial to implement on most implementations.

The absence of such casts is certainly not a defect.  But it would be
reasonable to request that the standard be extended to include such casts.


-- 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://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: Wil Evers <bouncer@dev.null>
Date: 2000/11/20
Raw View
In article
<bill-1811000732440001@216-178-255-150.sfo3.phoenixdsl.net>, Bill
Gibbons wrote:

> In article <8uuf4l$2v28s$1@ID-39279.news.dfncis.de>,
> "Jeremy Furtek" <jeremyf@believe.com> wrote:

> > However, when the Derived object is accessed via a
> > pointer-to-member, the conversion seems undefined or
> > inconsistently defined (see original post):
> >
> > Derived Container::* pmd = &(Container::d);  // This works fine
> > Base Container::* pmb = pmd; // Doesn't work.....why not?
>
> There is no real reason for this restriction except the general
> rule that the language shouldn't be made more complex without a
> compelling reason.

[snip]

> The absence of such casts is certainly not a defect.  But it would
> be reasonable to request that the standard be extended to include
> such casts.

So what about pointers to functions?  Consider:

      struct Base { };
      struct Derived : Base { };
      Derived* f();
(1)   Base* (*pf)() = &f;

Or, in terms of member functions:

      struct X { Derived* g(); };
(2)   Base* (X::*pmf)() = &X::g;

Or indeed:

      struct Foo { };
      struct Bar { Bar(const Foo&); };

      Foo f();
(3)   Bar (*pf)() = &f;
      struct X { Foo g(); };
(4)   Bar (X::*pmf)() = &X::g;

Allowing (3) and (4) would nicely match any relaxation of the
restrictions on covariant return types.

- Wil

--
Wil Evers, DOOSYS IT Consultants, Maarssen, Holland
[Wil underscore Evers at doosys dot 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://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]