Suppose I have a polymorphic hierarchy of classes with a common base:
struct Base { ~virtual Base() = default; };
I have inherited a large codebase which contains a long series of accessor functions (one for each derived type) that obtain a derived pointer via reinterpret_cast
:
Derived * Get() // Derived inherits from Base
{
Base * b = lookup_derived();
return reinterpret_cast<Derived *>(b);
}
Obviously the code should be using static_cast
or dynamic_cast
(depending on whether the base is virtual). However, because this translation unit is large and the definitions of all the derived classes are jointly huge, the TU does not contain the definition of Derived
, but only its declaration.
I would like to make this code more robust by adding to each derived class definition a static assertion that this reinterpret cast will produce the correct result. Essentially, I want something like this:
struct Derived : Base
{
static_assert(static_cast<Derived *>(std::declval<Base *>()) ==
reinterpret_cast<Derived *>(std::declval<Base *>()));
// ...
};
This constructions does not work of course since declval
must not be evaluated, and the result of a reinterpret cast is not a constant expression. Is there any standard C++ mechanism to perform such a test statically? (The alternative would be a runtime check on this
in the class constructor.)
Edit: Based on Aaron's post, I struck me that the question could be phrased entirely without reinterpret_casts:
static_cast<void *>(std::declval<Derived *>()) ==
static_cast<void *>(static_cast<Base *>(std::declval<Derived *>()))
I'm not sure if this will be good enough for the setup you have, but this code on ideone works for me (clang 3.5.0 and g++ 4.9.3).
Updated to cast in the other direction, i,e. Derived*
-to-Base*
, to more closely match the question. And also updated to use static_cast<void*>
explicitly instead of C-style casting and reinterpret_cast
.
template<typename D, typename B>
struct CheckCasting {
static D d_static;
constexpr
static B* bp = &d_static; // the original object is D,
// that allows us to static_cast both ways
static
constexpr bool static_equals_reinterpret() {
return static_cast<void*>(static_cast<D*>(bp))
== static_cast<void*>( bp );
}
};
struct Base {
constexpr Base() : i(0) {}
int i;
};
struct derived_with_virtual : public Base {
derived_with_virtual() {}
virtual void foo() { }
};
struct without_virtual : public Base {
without_virtual() {}
};
static_assert( ! CheckCasting<derived_with_virtual, Base> :: static_equals_reinterpret() ,"");
static_assert( CheckCasting<without_virtual , Base> :: static_equals_reinterpret() ,"");
A few comments:
void*
with reinterpret_cast, but clang didn't like that. "note: reinterpret_cast is not allowed in a constant expression".static_assert
inside the Derived class without success.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With