Search code examples
c++inheritancecastingunions

Cast pointer to union to known base class of unknown active member


Suppose I have a union and I know the active member derives from some (non-standard layout) base class, but I don't know which specific member is active. Is it legal to cast a pointer to that union, via void *, to a pointer to the base class, then use that base pointer?

For example, is this (which does compile with g++ 11.3.0 with -std=c++23) legitimate?

class base { public: virtual bool foo() = 0; };

class derived_1 : public base { bool foo() override { return true; }; };

class derived_2 : public base { bool foo() override { return false; }; };

union some_base {
  derived_1 x;
  derived_2 y;

  bool foo() {
    return static_cast<base *>(static_cast<void *>(this))->foo();
  };
};


Solution

  • The union object that this points to is pointer-interconvertible with the active derived_1 or derived_2, but it is not pointer-interconvertible with the base class subobject of either. Pointer-interconvertibility between base and derived classes applies only to standard layout classes.

    Therefore the cast will not result in a pointer to the base class subobject and the member access will have undefined behavior as the actual type of the pointed-to object is not similar to that of the expression.

    The layout of the classes is not relevant to this. It is more similar to an aliasing violation. However, even regarding layout, there is nothing requiring the implementation to place the Base subobject at zero offset (or at equal offsets at all) into derived_1 and derived_2.

    The ABI specification will make a determination regarding the last point though. Then assuming that the layout is appropriate, it may very well work in practice. I am not sure whether or to what degree compilers use this aliasing-type violation for optimization in practice.