Pointers-to-members

Mark Mitchell mark at codesourcery.com
Wed Feb 23 19:28:51 UTC 2000


  >>>>> Mark Mitchell <mark at codesourcery.com> writes:

   >   o A pointer-to-derived can be converted to a pointer-to-base.  This
   >     will normally increase the `this' pointer.  The standard is a
   >     little unclear here, but I think it wants to say that this is
   >     illegal precisely in the cases where the offset would go negative:

   >       [expr.static.cast]

   >       If class B contains the original member, or is a base or derived
   >       class of the class containing the original member, the resulting
   >       pointer to member points to the original member.  Otherwise, the
   >       result of the cast is undefined.

  I don't see anything in the quoted text that would suggest that this is
  illegal (or even undefined).  The standard then goes on to say explicitly
  that it's OK to cast to a base that doesn't contain the member:

  [Note: although class B need not contain the original member, the dynamic
  type of the object on which the pointer to member is dereferenced must
  contain the original member.]

That's what I meant by unclear.  It seems to me that the paragraph I
quoted was perhaps written with only single inheritance in mind.  I'm
not sure what implementation the framers had in mind for multiple
inheritance.

What does it mean to be a "class containing the original member"?  I
wasn't sure whether given:

  struct S { char c; };
  struct U { char d; };
  struct T : public U, public S { };

tat `T' contains the "original member" `d', or whether only `U' does,
for the purposes of this discussion.

If you interpretation is correct, then, AFAIK, most current
implementations behaves wrongly on this example (reposted from my
earlier message):

  struct S { char c; };
  struct U { char d; };
  struct T : public U, public S { };

  typedef char S::*sp;
  typedef char T::*tp;

  int main ()
  {
    sp s;
    tp t;

    t = &T::d;
    s = static_cast<sp> (t);

    if (s == 0)
      return 1;
  }

Both g++ and EDG-based compilers will say that `s' is NULL -- which is
bogus, if the cast is well-defined.  I assume Cfront would have gotten
this wrong as well, since the EDG ABI is pretty much the Cfront ABI.
So, there's certainly no real history of this working, for whatever
that's worth.

I guess using 0x80000000 for NULL is probably better, though -- this
example will work, and you don't have to subtract one when
dereferencing the pointer-to-member.

--
Mark Mitchell                   mark at codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com




More information about the cxx-abi-dev mailing list