2016-04-15 2 views
1

Ich gehe derzeit durch r-Wert-Referenzen und verschiebe Semantik, und ich sehe eine seltsame Diskrepanz in meinen eigenen Codierungs-Experimenten.Warum kann ich bei Verwendung von std :: forward eine l-Wert-Referenzfunktion aufrufen, während ich einen r-Wert übergebe?

der folgende Code Gegeben:

#include <iostream> 

using namespace std; 

class X{}; 

void g(X&& t) // A 
{ 
    cout << "Rref call" << endl; 
}  

void g(X& t) // B 
{ 
    cout << "Lref call" << endl; 
}  

template<typename T> 
void f(T&& t) 
{ 
    g(forward<T>(t)); 
} 

int main() 
{ 
    X x; 
    f(x); // 1 
    f(X()); // 2 

    return 0; 
} 

Wird die erwartete Ausgabe hier erzeugen:

Lref nennt Rref zu nennen

Allerdings, wenn ich voran gehen und lösche die überladene Funktion g, die eine r-Wert-Referenz nimmt (oben auf Kommentarzeile // A bezeichnet), habe ich folgende Ausgabe:

Lref nennen

Wie funktioniert das aus Lref zu nennen? Warum beschwert sich der Compiler nicht über einen Anruf an g(X& t), während er versucht, eine X&& zu übergeben?

+3

Verwenden Sie Visual Studio? Wenn ja, hat es eine [nicht-standardmäßige Erweiterung] (http://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to-a-temporary-object) zu Erlauben Sie Provisorien, an nicht-konstante Referenzen zu binden. Es schlägt fehl [in diesem Beispiel] (http://ideone.com/TcJbJA). –

+0

James, das sieht genau so aus. War verrückt geworden und versuchte herauszufinden, was passiert ist. Herzlichen Dank. – Joefers

Antwort

3

Wenn Sie die g(X&& t) Überladung auskommentieren, verwenden Sie eine MSVC extension, die das Binden von rvalues ​​an Nicht-const lvalue-Referenzen ermöglicht. Wenn Sie die Warnstufe auf /W4 stellen, wird MSVC Ihnen mitteilen, dass eine nicht standardmäßige Erweiterung verwendet wird.

Sowohl gcc und clang fail to compile der Code mit dieser Überlastung auskommentiert.

+0

Yup! War mit Visual Studio und es war glücklich, dies zu akzeptieren. Danke schön. – Joefers

+0

Dies ist einer der schrecklichsten Bugs in MSVC. Und obwohl es in den Tagen, in denen es keine rvalue-Referenzen gab, vielleicht einen Sinn hatte, hat es jetzt Sinn. Sie sollten es für C++ 11-Code deaktiviert haben. – SergeyA

+0

@SergeyA Nun, es ist ausgeschaltet, wenn Sie mit '/ W4' und'/WX' kompilieren, wie Sie sollten :) Aber ich will keine Ausreden für sie machen, das ist eine schreckliche Erweiterung. – Praetorian