Kann ein Element eines Tupels auf ein anderes verweisen?

8

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:

%Vor%

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]:

%Vor%

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%     
Benjamin Kay 26.07.2012, 18:25
quelle

2 Antworten

5

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%     
Howard Hinnant 26.07.2012, 18:41
quelle
0

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.

    
Puppy 26.07.2012 18:44
quelle