Pointers-to-members

Mark Mitchell mark at codesourcery.com
Wed Feb 23 00:03:13 UTC 2000


  > Yes.  I apologize for my own idiocy.
				 ^^^^^^
  Another typo, I guess :-)

No, that's the right spelling. :-) Check www.dictionary.com.  I might
be an idiot, but at least I can spell! :-)

  Ach, but, what is the value for the NULL pointer to data member? I guess -1
  would do, unless there are cases I can't think of where the pointer to member
  would legitimately have a negative value. Maybe 0x8000000000000000
  is better...

I'm a step ahead of you. :-) I already started a thread on precisely
this.  Here's some more analysis:

  o All pointer-to-member offsets start out non-negative.
  o Only casts which would increase the `this' pointer could cause
    the pointer-to-member to go negative.
  o A reinterpret_cast leaves the value unspecified, except that:

     - NULL is converted to NULL
     - If you convert back, you're OK.

    But, therefore, converting a non-NULL value to NULL is explicitly
    permitted by the standard.

  o A pointer-to-base can be converted to a pointer-to-derived via
    an implicit conversion/static_cast.

    It's illegal to do this if the base is virtual.  But, that's the
    only case in which the `this' pointer can increase.

  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.

    Consider this program:

      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;
      }
  
   With GCC, this program wil return 1, i.e., the `&T::d' pointer has
   become NULL when converted to `char S::*'.  But, I think this
   behavior is OK: `S' does not contain the original member `U::d'.

So, adding `1' to the offset (and using `0' for NULL) is OK; so is
using `-1' for NULL, and using the offset for the pointer-to-member
itself.

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




More information about the cxx-abi-dev mailing list