Ich möchte das Union-Element im Konstruktor basierend auf einem Argument initialisiert auswählen. Im Folgenden ist ein Beispiel, das funktioniert:C++ 14 constexpr union konditionale Initialisierung in Konstruktor
struct A {
union {
int i;
float f;
};
A(double d, bool isint) {
if (isint) new(&i) int(d);
else new(&f) float(d);
}
};
Während ich int
und float
verwenden, das Ziel ist, mit anderen komplexeren Typen (aber immer noch zulässige in einer C++ 14 union) zu arbeiten, damit die Verwendung von Placement-Neu (und keine Aufgabe).
Das Problem ist, dass dieser Konstruktor nicht constexpr
als Placement-Neu ist in constexpr
Methoden nicht zulässig ist. Gibt es einen Weg dazu (abgesehen davon, dass das Argument isint
zum formalen System gehört)? Irgendeine Art von konditionalen Initialisierungsliste würde funktionieren, aber ich bin mir nicht bewusst, wie ich das machen könnte.
IIRC, Typ Punning ist (im Allgemeinen) innerhalb konstanter Ausdrücke verboten. Sie können beispielsweise alle Mitglieder separat speichern ("struct" statt "union") und die Kapselung verwenden, um zu erzwingen, dass nur eines der Mitglieder aktiv ist. – dyp
Ich denke, es hängt davon ab, welche Art von Typ Punning Sie in Betracht ziehen. Ich kann sicherlich einen Konstruktor erklären, der 'i' initialisiert und einen anderen, der' f' initialisiert. Nur ein Mitglied der Gewerkschaft kann zu irgendeinem Zeitpunkt "aktiv" sein, aber ich versuche nicht, dies zu entfernen. Ich würde gerne dem Compiler mitteilen, welches Mitglied aktiv ist. – cshelton
Sie haben Recht. Diese Art der Verwendung von Placement-Neu umgeht das Typsystem nicht wirklich. - Es ist möglich, dies in einer externen Funktion, z. 'constexpr A make_A (doppelter d, bool isint) {if (isint) return A (d, true_type {}); sonst gib zurück A (d, false_type {}); } '. Es sollte möglich sein, eine solche Funktion innerhalb des Konstruktors aufzurufen, wenn Sie stattdessen nicht anonyme Verbindungen verwenden.Etwas wie 'struct A {union storage {int i; float f; Speicher (double d, true_type); Speicher (double d, false_type); } m; A (double d, bool isint): m (make_storage (d, isint)) {}}; ' – dyp