Coerce pointer to member to most derived type

164 views Asked by At

Consider this type hierarchy:

struct A {
    int x;
};

struct B : A {
    int y;
};

The type of &B::y is int B::*, but the type of &B::x is int A::*. It can be convertible to int B::*, which is what I need, but I need to explicitly perform that conversion.

Is there a handy way of deducing the type to be a pointer to a member of the class I specified? After all, if I wanted an A::* to x I could do &A::x.

1

There are 1 answers

0
The Vee On

Such conversion would not be possible in case of virtual inheritance. Assume

struct A {
  int x;
};

struct B : virtual A {
  int y;
};

and two functions,

int f(B* pB) {
  int A::*pX = &A::x; // or &B::x, identical but clearer this way
  return pB->*pX;
}

int g(B* pB) {
  int B::*pY = &B::y;
  return pB->*pY;
}

f(B*) needs to make a vtable lookup in order to find the base pointer of A instance within *pB while g(B*) only applies an offset to pB. Therefore the object &A::x can not be expressed as an instance of a type int B::*, it needs a different runtime logic to evaluate with a pointer to B than an int B::* would.

Even though B is the most derived class here and now, one might define another class C inheriting both A and B in a different compilation unit and want to pass a C* to f(). So the offset of A within B can not be taken for fixed.

One could argue that the language could permit the conversion if no virtual inheritance is present, or in anonymous namespaces, or... but it was probably easier to disallow it consistently.