2016-07-14 18 views
3

Let sagen, dass ich diesen Code habestd :: bewegen, std :: vorwärts, Werttyp und Vorlage Abzug

template <typename T> void Swap(T&& a, T&& b) { 
    T tmp = std::move(a); 
    a = std::move(b); 
    b = std::move(tmp); 
} 

int main() 
{ 
    int a = 2; 
    int b = 3; 
} 

Nach meinem Verständnis von this talk, wenn Swap(a, b) Aufruf sollte der Compiler die Tatsache ableiten, dass T&& sollte T& sein und es konvertieren. Aber in diesem Fall gibt GCC mir folgende Fehlermeldung:

error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'std::remove_reference<int&>::type {aka int}' 
T tmp = std::move(a); 

entweder ich habe SwapSwap(std::forward<int>(a), std::forward<int>(b)) mit anrufen oder Swap(std::move(a), std::move(b)) oder der Swap Unterzeichnung durch Swap(T& a, T& b) zu ersetzen.

Warum ist das der Fall? Was ist die korrekte Verwendung hier?

+2

"* der Compiler sollte die Tatsache ableiten, dass' T && '' T & 'sein sollte * Er, richtig, so dass die erste Zeile' T & tmp = std :: move (a); 'was unsinnig ist, als Sie können einen Rvalue nicht an eine nicht konstante Lvalue-Referenz binden. Du scheinst das zu wissen, also verstehe ich nicht, was deine eigentliche Frage ist ... – ildjarn

+1

Der Austausch von zwei Rvalues ​​ist vielleicht ein bisschen albern: 'Swap (1 + 2, 2 + 1)' ...? Etwas wie 'std :: exchange' kann etwas mehr Wert haben. –

+0

@ildjarn: Nach meiner Erfahrung erleben Menschen manchmal eine "blinde Zone" in ihrem Denken. Wie die blinde Zone in der Mitte Ihres Sichtfelds bemerken Sie es überhaupt nicht, wenn Sie Ihr visuelles Subsystem nicht zwingen, z. eine schwimmende Wurst (einige Kinder erfreuen sich daran, wenn man ihnen beibringt, wie man das macht). Meine häufigste Blindzone ist der Binärschalter. Vielleicht ist es derselbe Mechanismus, der den religiösen Glauben unterstützt. Wie auch immer, es ist üblich. –

Antwort

6

Sie müssen dies:

template <typename T> void Swap(T&& a, T&& b) 
{ 
    using U = typename std::remove_reference<T>::type; 

    U tmp = std::move(a); 
    a = std::move(b); 
    b = std::move(tmp); 
} 

Wie Sie in Ihrer Frage angedeutet, in Ihrem Beispiel wird T als int& abgeleitet, und die Initialisierung int& tmp = std::move(a); ist schlecht ausgebildet.

+2

Beat mich dazu .. :( –