Let's say I have these types:
struct A {
int a;
};
struct B {
int b;
};
struct C : public A, public B {
int c;
};
A C*
pointer can be cast to A*
pointer without adjusting the actual address at all. But when C*
is cast to B*
, the value must change. I'd like to ensure that two related types I have can be cast to each other without a change in address (i.e. that there is no multiple inheritance, or that the base class is the first base of the derived class). This could be checked at run-time, e.g. like so
assert(size_t(static_cast<A*>((C*)0xF000) == 0xF000);
assert(size_t(static_cast<B*>((C*)0xF000) != 0xF000);
That works. But this information is known at compile time, so I'm looking for a way to do a compile-time assert on it. The obvious ways of converting the above to a static assert (e.g. replace assert
with BOOST_STATIC_ASSERT
give the error "a cast to a type other than an integral or enumeration type cannot appear in a constant-expression" with g++ 4.2.
Portability isn't too important. Using gcc extensions, or hacky template tricks would all be fine.
Update: Found that almost the same question has been asked before: C++, statically detect base classes with differing addresses?. Using offsetof()
is the only useful suggestion there too.
Based on a suggestion from MSalters, and an answer from C++, statically detect base classes with differing addresses?, here is the closest thing to an answer I can come up with. It's probably gcc-specific, and requires knowing some member of the base class:
#pragma GCC diagnostic ignored "-Winvalid-offsetof" // To suppress warning.
BOOST_STATIC_ASSERT(offsetof(C, a) == offsetof(A, a));
BOOST_STATIC_ASSERT(offsetof(C, b) != offsetof(B, b));
#pragma GCC diagnostic warn "-Winvalid-offsetof"
Obviously this is both inconvenient and scary (requires to know a member and to turn off a warning).