Update: Siehe die vollständige Antwort unten. Die kurze Antwort ist nein, nicht direkt. Sie können eine indirekte Referenz mit std::reference_wrapper
erstellen oder den gleichen Effekt allgemeiner mit Zeigern erzielen (aber ohne den syntaktischen Zucker und die zusätzliche Sicherheit von Referenzen).
Ich frage, weil Tupel in C ++ 11 eine bequeme variadische Speichereinheit bilden. In der Theorie erscheint es sinnvoll, dass ein Element eines Tupels einen Verweis auf ein anderes Element im selben Tupel enthält. (Ersetze "Referenz" durch "Zeiger" und es funktioniert in der Praxis.) Der Teufel ist die Details zum Konstruieren eines solchen Tupels. Betrachten Sie das folgende Beispiel:
%Vor% Das zweite Element im Tupel t1
verweist auf die automatische Variable a
anstelle des ersten Elements in t1
. Gibt es eine Möglichkeit, ein Tupel so zu konstruieren, dass ein Element des Tupels einen Verweis auf ein anderes Element im selben Tupel enthalten kann? Ich bin mir bewusst, dass Sie dieses Ergebnis erzielen könnten, indem Sie ein Tupel von Referenzen erstellen, wie dieses:
Aber für meine Zwecke ist das Betrug, da das zweite Element in t2
immer noch auf ein Objekt verweist, das außerhalb des Tupels lebt. Die einzige Art und Weise, wie ich es mir vorstellen kann, kompiliert gut, kann aber undefiniertes Verhalten enthalten [Bearbeitet, um ein präziseres Beispiel von Howard Hinnant zu reflektieren]:
Edit: Hier ist ein minimales Testprogramm, das mit einem Nicht-Null-Exit-Status zurückkommt, wenn es mit g ++ 4.7 mit -O2 oder höher kompiliert wird. Dies deutet auf ein nicht definiertes Verhalten oder einen Fehler in gcc hin.
%Vor%Das funktioniert für mich:
%Vor%Aktualisieren
Ich habe gerade auf der CWG-Mailingliste nach diesem Fall gefragt. Mike Miller versichert mir, dass dies ein undefiniertes Verhalten nach 3.8p6 bullet 2 ist:
... Das Programm hat ein undefiniertes Verhalten, wenn:
...
- Der Wert glvalue wird verwendet, um auf ein nicht statisches Datenelement zuzugreifen oder eine nicht statische Elementfunktion des Objekts oder
aufzurufen...
Es wäre wohldefiniertes Verhalten, wenn tuple
ein Aggregat wäre, aber weil tuple
einen vom Benutzer deklarierten Konstruktor hat, gilt 3.8p6b2.
Aber das funktioniert und vermeidet UB:
%Vor% Soweit mir bekannt ist, ist es ein wohldefiniertes Verhalten, um ein Objekt zu aliasieren, das noch nicht existiert. Dies ist die gleiche Situation, die Sie mit this
in der Initialisierungsliste des Konstruktors finden können, was bedauerlich, aber häufig und wohldefiniert ist.
Tags und Links c++ c++11 undefined-behavior tuples