Sagen wir, ich habe diese Typen:
Code: Select all
struct A {
int a;
};
struct B {
int b;
};
struct C : public A, public B {
int c;
};
Ein C*-Zeiger kann in einen A*-Zeiger umgewandelt werden, ohne dass die tatsächliche Adresse überhaupt angepasst wird. Aber wenn C* in B* umgewandelt wird, muss sich der Wert ändern.
Ich möchte sicherstellen, dass zwei verwandte Typen, die ich habe, ohne Adressänderung ineinander umgewandelt werden können (d. h. dass es keine Mehrfachvererbung gibt oder dass die Basisklasse die erste Basis der abgeleiteten Klasse ist). Dies könnte zur Laufzeit überprüft werden, z.B. so
Code: Select all
assert(size_t(static_cast((C*)0xF000) == 0xF000);
assert(size_t(static_cast((C*)0xF000) != 0xF000);
Das funktioniert. Aber diese Informationen sind zur Kompilierungszeit bekannt, daher suche ich nach einer Möglichkeit, eine Assertion zur Kompilierungszeit darauf durchzuführen. Die offensichtlichen Möglichkeiten, das Obige in eine statische Zusicherung umzuwandeln (z. B. das Ersetzen von Assert durch BOOST_STATIC_ASSERT, führen zu dem Fehler „Eine Umwandlung in einen anderen Typ als einen Integral- oder Aufzählungstyp kann nicht in einem Konstantenausdruck erscheinen“ mit g++ 4.2.
Portabilität ist nicht so wichtig. Die Verwendung von GCC-Erweiterungen oder hackigen Vorlagentricks wäre alles in Ordnung.
Update: Ich habe festgestellt, dass fast die gleiche Frage schon einmal gestellt wurde: C++, Basisklassen mit unterschiedlichen Adressen statisch erkennen? Die Verwendung von offsetof() ist auch dort der einzige nützliche Vorschlag.