Topic: Fwd: pointer to member conversion to a pointer to member that


Author: v.Abazarov@comAcast.net (Victor Bazarov)
Date: Fri, 20 Aug 2004 23:27:25 GMT
Raw View
Hyman Rosen wrote:
> Victor Bazarov wrote:
>
>> The basic idea is: if for two classes B and D exists an implicit
>> conversion from { D* to B* } (plain vanilla ptr-to-derived to ptr-to-base
>> conversion, see 4.10), then the conversion { D T::* to B T::* } for an
>> arbitrary class T should exist as well.  I there anything I am missing?
>
>
> When the converted pointer is called, there may need to be fixup code
> generated to the D -> B conversion, so I don't think handling this is
> particularly easy. Here's example code:
>
> struct A { double a; };
> struct B { unsigned b; };
> struct AB : A, B { long ab; };
> struct X { AB ab() { return AB(); } };
>
> int main()
> {
>     AB (X::*fab)() = &X::ab;
>     B (X::*fb)() = fab;      // The suggested conversion
>     X x;
>     B b = (x.*fb)();
> }

What fixup code?

I don't think that I asked for this type of conversion.  I was talking
member objects, not member functions.  Here is a simple[r] example of
what is needed:

   struct B { virtual int foo() const = 0; };
   struct D : B { virtual int foo() const { return 42; } };
   struct DD : B { virtual int foo() const { return 43; } };
   struct X { B X::* pb; D d; DD dd;
       int dofoo() const { (this->*pb).foo(); } };

   int main()
   {
       X x;
       x.pb = &X::d;  // ***
       int fortytwo = x.dofoo(); // makes fortytwo == 42
       x.pb = &X::dd; // ***
       int fortythree = x.dofoo(); // makes fortythree == 43
   }

The 'X::dofoo' function is of interest.  It takes the pointer to member
of X of class B and calls the virtual function on it.  What should happen
is this: whatever this pointer points to should get its final overrider
called.  If I make pb point to a 'd', the D::foo should be called but for
the object 'd' in the 'x'.  Same if pb points to 'dd'.

Right now it "works" if a reinterpret_cast is used on the right sides of
the assignments on lines marked with '***'.  But reinterpret_cast does not
allow that type of conversion either.  I submit an implicit conversion of
that sort should exist.  Is there anything that would make it difficult?

Thanks.

Victor

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]





Author: v.Abazarov@comAcast.net (Victor Bazarov)
Date: Mon, 23 Aug 2004 15:55:41 GMT
Raw View
Bob Hairgrove wrote:
> On Fri, 20 Aug 2004 23:27:25 GMT, v.Abazarov@comAcast.net (Victor
> Bazarov) wrote:
>
>
>>I don't think that I asked for this type of conversion.  I was talking
>>member objects, not member functions.  Here is a simple[r] example of
>>what is needed:
>>
>>  struct B { virtual int foo() const = 0; };
>>  struct D : B { virtual int foo() const { return 42; } };
>>  struct DD : B { virtual int foo() const { return 43; } };
>>  struct X { B X::* pb; D d; DD dd;
>>      int dofoo() const { (this->*pb).foo(); } };
>>
>>  int main()
>>  {
>>      X x;
>>      x.pb = &X::d;  // ***
>>      int fortytwo = x.dofoo(); // makes fortytwo == 42
>>      x.pb = &X::dd; // ***
>>      int fortythree = x.dofoo(); // makes fortythree == 43
>>  }
>>
>>The 'X::dofoo' function is of interest.  It takes the pointer to member
>>of X of class B and calls the virtual function on it.  What should happen
>>is this: whatever this pointer points to should get its final overrider
>>called.  If I make pb point to a 'd', the D::foo should be called but for
>>the object 'd' in the 'x'.  Same if pb points to 'dd'.
>>
>>Right now it "works" if a reinterpret_cast is used on the right sides of
>>the assignments on lines marked with '***'.  But reinterpret_cast does not
>>allow that type of conversion either.  I submit an implicit conversion of
>>that sort should exist.  Is there anything that would make it difficult?
>
>
> Actually, as John Harrison pointed out to me in another thread on
> comp.lang.c++, this can also be done much more easily using normal
> pointers, i.e.:
>
> #include <iostream>
> #include <ostream>
>
> struct B { virtual int foo() const = 0; };
> struct D : B { virtual int foo() const { return 42; } };
> struct DD : B { virtual int foo() const { return 43; } };
> struct X { B * pb; D d; DD dd;  // pb is now simply a B*
>    int dofoo() const { return pb->foo(); } };
>
> int main()
> {
>    X x;
>    x.pb = &(x.d);  // ***
>    int fortytwo = x.dofoo(); // makes fortytwo == 42
>    x.pb = &(x.dd); // ***
>    int fortythree = x.dofoo(); // makes fortythree == 43
>
>    std::cout << "fortytwo:\t" << fortytwo << std::endl;
>    std::cout << "fortythree:\t" << fortythree << std::endl;
>    return 0;
> }

Right.  This works fine.  Now imagine this situation:
--------------------------------
struct B { virtual int foo() const = 0; };
struct D : B { virtual int foo() const { return 42; } };
struct DD : B { virtual int foo() const { return 43; } };
struct X { static B X::* pb; D d; DD dd; // ******* pb is now static!
     int dofoo() const { (this->*pb).foo(); } };

int main()
{
     X x[5];
     X::pb = &X::d;  // ***
     for (int i = 0; i < 5; ++i)
         int fortytwo = x[i].dofoo(); // makes fortytwo == 42
     X::pb = &X::dd; // ***
     for (int i = 0; i < 5; ++i)
         int fortythree = x[i].dofoo(); // makes fortythree == 43
}
--------------------------------

In this example, the 'pb' member is static.  Yes, I have to admit this
example is somewhat artificial, but imagine that there is some kind of
global dispatch mechanism that should change the behaviour of _all_ X
objects at some point without knowing how many there are.  It could be
done with a flag and then every object has to check the flag and do as
prescribed (which is a bit less efficient, probably).

Anyway, in this case, we cannot make 'pb' a pointer to an object, simply
because that has to be done for every instance of 'X'.  What to do in
this case?

Thank you for your interest in this problem.  I wish I could get a bit
more participation from other frequents here.

Victor

---
[ 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.jamesd.demon.co.uk/csc/faq.html                       ]