2016-06-22 23 views
6

Also fragte ich this question und ich bastelte um es zu lösen über static_cast. (Übrigens ist es das Problem zu lösen, ich bin nur nicht sicher, ob ich verstehen, warum.)Was macht static_cast <T> zu einem T &?

Im Code:

vector<int> foo = {0, 42, 0, 42, 0, 42}; 
replace(begin(foo), end(foo), static_cast<int>(foo.front()), 13); 

Ist static_cast einfach ein R-Wert int Konstruktion? Was ist der Unterschied zwischen dem, und nur dem Ruf:

replace(begin(foo), end(foo), int{foo.front()}, 13); 

EDIT:

Wie static_cast durch die Antworten gefolgert tut scheint ein R-Wert int zu konstruieren: http://ideone.com/dVPIhD

Aber diese Code funktioniert nicht auf Visual Studio 2015. Ist das ein Compiler-Fehler? Testen Sie hier: http://webcompiler.cloudapp.net/

+0

Ich habe kein Zitat Standard mich zu sichern, aber ich denke, Sie können '+ foo.front()' eine Kopie des Wertes zu erhalten, anstelle einem Verweis auf das Symbol – KABoissonneault

Antwort

6
  1. Ja, es ist die gleiche wie int{...} ist, es sei denn, .front() eine Art zurückgeführt, die eine Verengung Umwandlung erforderlich. In diesem Fall wäre int(...) identisch.

  2. Im Falle eines Programmierfehlers ist die statische Umwandlung etwas weniger wahrscheinlich, etwas Gefährliches zu tun, wie einen Zeiger in einen Int als int(...) umzuwandeln.

Hinweis der Gussergebnisse in undefiniertem Verhalten als Frontelement eliminiert wird durch den Betrieb ersetzen geändert, und die std::replace brechen könnte.

würde ich

template<class T> 
std::decay_t<T> copy_of(T&& t){return std::forward<T>(t); } 

mich hier verwenden.

Was, warum dies in MSVC nicht funktioniert ...

MSVC nimmt helfend Situationen, in denen Sie eine Variable vom Typ gegossen T zu einem T und geht nichts zu tun. Dies bricht Ihren Code.

Es gibt eine compiler flag (/Zc:rvalueCast), die Sie verwenden können, damit MSVC Ihren Code nicht mehr bricht.

+0

Ist 'copy_of'standard oder du sagst, dass ich das einfach umsetzen soll? –

+0

@jona Ich schlug vor, dies zu implementieren, da es eine Reihe von Anwendungsfällen hat und überflüssige Wiederholung vermeidet. – Yakk

+0

Also habe ich meine Frage geklärt, indem ich auf den Unterschied zwischen Visual Studio und gcc hingewiesen habe. Es tut uns leid, die Torpfosten auf dich zu ziehen. –

5

Die Mitgliedsfunktion front gibt einen Verweis auf das erste Element eines nicht leeren Vektors zurück.

Auf der anderen Seite Standard-Algorithmus replace erklärt wie

template <class ForwardIterator, class T> 
    void replace (ForwardIterator first, ForwardIterator last, 
       const T& old_value, const T& new_value) 

nimmt den dritten Parameter auch durch Bezugnahme eingeschlossen. Somit kann im Allgemeinen das erste Element des Vektors durch den Algorithmus geändert werden, und als Ergebnis kann die Verarbeitung anderer Elemente des Vektors durch den Algorithmus inkorrekt sein.

Mit static_cast wird ein temporäres Objekt erstellt und nicht vom Algorithmus geändert. Die Verarbeitung aller Elemente des Vektors ist also korrekt.

Für mich schlug ich dann einen C++ - Vorschlag vor, das Schlüsselwort in solchen Fällen zu verwenden. Zum Beispiel

replace(begin(foo), end(foo), auto(foo.front()), 13); 
+1

Der Vorschlag "Auto" ist sehr elegant. +1 –

+1

Der automatische Vorschlag nicht kompilieren: http://coliru.stacked-crooked.com/a/27328ba4ae68d68d – NathanOliver

+1

@NathanOliver Wie in der Antwort gesagt, ist es nur ein Vorschlag – KABoissonneault