Search code examples
c++crtp

How to tell the byte offset between a base class and a derived class?


I have a CRTP-like construct:

class Derived : public Base<Derived>

I need to calculate a pointer to a Derived object from a pointer to Base<Derived> object via reinterpret_cast. I cannot use dynamic_cast because I'm not using virtual functions here.

The types are given, I do have the pointer to the Base<Derived> object. I need the byte offset between the two types, so I can use reinterpret_cast. How do I do this (without undefined behavior)? Is it possible to do at compile-time / save as a static constexpr variable (I'm using C++20)?


Solution

  • There is no need for offset calculations or reinterpret_cast.

    If you are sure that the object is indeed a Derived one, you can simply use static_cast:

    Derived derived;
    Base<Derived> * pBase = &derived;
    
    Derived * pDerived = static_cast<Derived*>(pBase);
    

    Note that if pBase above does not actually point to a Derived object, using static_cast in the last line will invoke undefined-behavior (UB).

    A side note:
    As @BenVoigt commented below, it is common to add a helper method to the CRTP base class that does exactly this cast.
    I.e. add something like this to Base<Derived> (replace Derived if needed with the actual template parameter name in Base):

    template <typename Derived>
    class Base {
    
        Derived * ToDerived() { return static_cast<Derived*>(this); }
        // ...
    };