gumik
gumik

Reputation: 623

Is reinterpret_cast from Derived<X> to Base<X> safe?

Consider following template classes.

template <typename X>
class Base
{
public:
    void method1() {...}
    void method2() {...}
    ...

private:
    int  member1;
    float member2;
    ...
};

template <typename X>
class Derived : public Base<X>
{
public:
    void m1() {...}
    void m2() {...}
// no members here
}

// similar with second set of classes SecBase, SecDerived

Base<SecBase<X>> originalObject;
Derived<SecDerived<X>>& wrapperRef = reinterpret_cast<Derived<SecDerived<X>>&>(originalObject);

These two classes has exactly the same members. Derived is something like a wrapper around Base. Is the cast in last line safe? What if we consider compiling with optimizations? Could compiler do some optimizations that it won't work?

Upvotes: 1

Views: 199

Answers (2)

Mike Seymour
Mike Seymour

Reputation: 254461

Is the cast in last line safe?

The cast is valid if the two classes are layout-compatible; that is

  • they both have standard layout, as defined in C++11 9/7
  • they both have the same non-static data members

It looks like the first condition is met; the second will be if none of the data member types depends on the template parameter (or, if it does, it resolves to the same type for both SecBase<X> and SecDerived<X>).

Having said that, I wouldn't describe it as "safe", since it would be easy to modify the code and accidentally break one of these conditions.

What if we consider compiling with optimizations? Could compiler do some optimizations that it won't work?

If they're not layout-compatible, then the program has undefined behaviour and you can't rely on anything. The behaviour could change depending on optimisation or other settings, or on the phase of the moon.

Upvotes: 3

Paul Evans
Paul Evans

Reputation: 27577

You should redesign your solution for this, something like:

template <typename X>
class Derived
{
    Base* pB_;
public:
    Derived(Base * pB) : pB_(pB) {}
    void m1() {pB_->method1()}
    void m2() {pB_->method2()}
}

Upvotes: 1

Related Questions