Austauschbare Klassentypen nur über Zeiger-Casting erstellen, ohne neue Objekte zuweisen zu müssen?

AKTUALISIEREN: Ich schätze "will das nicht, will das stattdessen" Vorschläge. Sie sind insbesondere dann nützlich, wenn sie im Zusammenhang mit dermotivierendes Szenario. Trotzdem ... unabhängig von Güte / Schlechtigkeit bin ich neugierig geworden, ein hartes und schnelles zu finden"ja das geht legal in C ++ 11" vs"nein so etwas ist nicht möglich".

Ich möchte einen Objektzeiger als anderen Typ "aliasen", für deneinziger Zweck einige Hilfsmethoden hinzufügen. Der Alias ​​kann der zugrunde liegenden Klasse keine Datenelemente hinzufügen (in der Tat ist es umso besser, je mehr ich verhindern kann, dass dies geschieht!). Alle Aliasnamen sind auf alle Objekte dieses Typs gleichermaßen anwendbar. Es ist nur hilfreich, wenn das Typensystem darauf hinweisen kann Alias ​​ist wahrscheinlich am besten geeignet.

Es sollten keine Informationen zu einem bestimmten Alias ​​vorhanden sein, der jemals im zugrunde liegenden Objekt codiert wurde. Aus diesem Grund sollte es Ihnen möglich sein, das Typsystem zu "betrügen" und nur eine Anmerkung zuzulassen, die beim Kompilieren überprüft wurde, aber letztendlich für das Laufzeit-Casting irrelevant ist. Etwas in diese Richtung:

Node<AccessorFoo>* fooPtr = Node<AccessorFoo>::createViaFactory();
Node<AccessorBar>* barPtr = reinterpret_cast< Node<AccessorBar>* >(fooPtr);

Unter der Haube macht die Fabrikmethode tatsächlich einNodeBase Klasse, und dann mit einem ähnlichenreinterpret_cast zurückgeben alsNode<AccessorFoo>*.

Die einfache Möglichkeit, dies zu vermeiden, besteht darin, diese Lightweight-Klassen so zu gestalten, dass sie Knoten umschließen und als Wert weitergegeben werden. Daher brauchen Sie kein Casting, sondern nur Accessor-Klassen, die das Node-Handle verwenden, um ihren Konstruktor einzubinden:

AccessorFoo foo (NodeBase::createViaFactory());
AccessorBar bar (foo.getNode());

Aber wenn ich das alles nicht bezahlen muss, will ich nicht. Dazu müsste beispielsweise für jede Art von umschlossenem Zeiger (AccessorFooShared, AccessorFooUnique, AccessorFooWeak usw.) ein spezieller Accessortyp erstellt werden. Diese typisierten Zeiger sollten für eine einzelne zeigerbasierte Objektidentität mit einem Alias ​​versehen werden schöne Orthogonalität.

Also zurück zu dieser ursprünglichen Frage:

Node<AccessorFoo>* fooPtr = Node<AccessorFoo>::createViaFactory();
Node<AccessorBar>* barPtr = reinterpret_cast< Node<AccessorBar>* >(fooPtr);

Es scheint, als gäbe es einen Weg, der hässlich sein könnte, aber nicht "gegen die Regeln verstößt". GemäßISO 14882: 2011 (e) 5.2.10-7:

Ein Objektzeiger kann explizit in einen Objektzeiger eines anderen Typs konvertiert werden.70 Wenn ein Wert v vom Typ "Zeiger auf T1" in den Typ "Zeiger auf Lebenslauf T2" konvertiert wird, ist das Ergebnis static_cast (static_cast (v)) Wenn sowohl T1 als auch T2 Standardlayouttypen (3.9) sind und die Ausrichtungsanforderungen von T2 nicht strenger als die von T1 sind, oder wenn einer der beiden Typen nichtig ist. Das Konvertieren eines Wertes vom Typ "Zeiger auf T1" in den Typ "Zeiger auf T2" (wobei T1 und T2 Objekttypen sind und die Ausrichtungsanforderungen von T2 nicht strenger als die von T1 sind) und zurück zu seinem ursprünglichen Typ ergibt das Original Zeigerwert. Das Ergebnis einer anderen derartigen Zeigerkonvertierung ist nicht spezifiziert.

Drilling in die Definition von a"Standard-Layout-Klasse", wir finden:

hat keine nicht statischen Datenelemente vom Typ Nicht-Standard-Layout-Klasse (oder Array solcher Typen) oder Verweis, undhat keine virtuellen Funktionen (10.3) und keine virtuellen Basisklassen (10.1) unddieselbe Zugriffskontrolle (Klausel 11) für alle nicht statischen Datenmitglieder hat, undhat keine Nicht-Standard-Layout-Basisklassen undentweder kein nicht statisches Datenelement in der am häufigsten abgeleiteten Klasse und höchstens eine Basisklasse mit nicht statischen Datenelementen oder keine Basisklassen mit nicht statischen Datenelementen undhat keine Basisklassen desselben Typs wie das erste nicht statische Datenelement.

Klingt so, als würde die Arbeit mit so etwas meine Hände ein wenig fesseln, ohne dass virtuelle Methoden in den Accessoren oder im Knoten vorhanden wären. Doch C ++ 11 hat anscheinendstd::is_standard_layout die Dinge unter Kontrolle zu halten.

Kann das sicher gemacht werden? Scheint in gcc-4.7 zu funktionieren, aber ich möchte sichergehen, dass ich kein undefiniertes Verhalten hervorrufe.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage