burnpanck
burnpanck

Reputation: 2196

Constexpr check if static_cast of pointers between two hierarchically related types changes the pointer value

For some specialised allocator-like thing I'm implementing, I would like to require that all objects that are going to be stored share a common base class as their first subobject. This allows me to keep a single pointer the common base class as both an indicator of the start of the object as well as to regain access to the original object using static_cast, assuming I have some way to know the type of the original object.

Specifically, I would like the following equality to always hold for any pointer ptr to a type Base, assuming no virtual inheritance between Derived and Base.

reinterpret_cast<char *>(static_cast<Derived*>(ptr)) == reinterpret_cast<char *>(ptr)

I assume that this equation holds either for all valid pointers of a given class hierarchy, or it doesn't hold for any valid pointer of a given class hierarchy. Is that correct?

Therefore, that check should be possible to be made at compile-time, without even knowing the runtime value of ptr. So is there a constexpr method to check if a static_cast between two related types changes the pointer value? The above equality seems not acceptable, as I found no constexpr way to create test pointer.

Upvotes: 1

Views: 518

Answers (1)

Jeff Garrett
Jeff Garrett

Reputation: 7428

You are asking about is pointer interconvertibility. There is a related trait std::is_pointer_interconvertible_base_of which isn't implemented yet in gcc and clang. See also the paper and issue. Pointer interconvertible types have the same address and their pointers can be casted between with reinterpret_cast.

I assume that this equation holds either for all valid pointers of a given class hierarchy, or it doesn't hold for any valid pointer of a given class hierarchy. Is that correct?

As you already noted, virtual inheritance foils this, but so does failure of the standard layout criteria. If Derived has multiple base classes, and Base isn't the first, it fails.

The question fails to motivate the requirement for having the same address. If that is not a requirement, static_cast to upcast from Derived to Base and to downcast from Base to Derived will just work so long as the inheritance relationship is not virtual, unambiguous, and public.

Upvotes: 3

Related Questions