2016-07-27 16 views
1

Das Programm L-Wert ist als unten:vorbei rvalue Raises binden kann nicht

#include <iostream> 
using namespace std; 

template <typename F, typename T1, typename T2> 
void flip2(F f, T1 &&t1, T2 &&t2) 
{ 
     f(t2, t1); 
} 

void g(int &&i, int &j) 
{ 
     cout << i << " " << j << endl; 
} 

int main(void) 
{ 
     int i = 1; 
     flip2(g, i, 42); 
} 

Der Compiler beschwert sich:

error: rvalue reference to type 'int' cannot bind to lvalue of type 'int' 

Aber mein Verständnis, wie T2 mit int instanziiert wird, dann ist die Art von t2 ist int&&, daher sollte es erlaubt sein, das erste Argument der Funktion g zu übergeben (int &&).

Was ist falsch mit meinem Verständnis?

Antwort

4
f(t2, t1); 

t2 hat einen Namen, so ist es ein L-Wert. Es ist Typ ist Rvalue, aber in einem Ausdruck ist der Typ ein Lvalue. Um es als eine rvalue-Referenz übergeben zu können, müssen Sie std::forward (move) verwenden oder Casting wäre hier unpassend, da T1 und T2 tatsächlich universelle Referenzen, nicht rvalue Referenzen sind, siehe Bearbeiten).

#include <iostream> 
using namespace std; 

template <typename F, typename T1, typename T2> 
void flip2(F f, T1 &&t1, T2 &&t2) 
{ 
     f(std::forward<T2>(t2), std::forward<T1>(t1)); 
} 

void g(int &&i, int &j) 
{ 
     cout << i << " " << j << endl; 
} 

int main(void) 
{ 
     int i = 1; 
     flip2(g, i, 42); 
} 

http://ideone.com/Aop2aJ

--- --- Warum

Bedenken Sie:

template<typename T> 
void printAndLog(T&& text) { 
    print(text); 
    log(text); 
} 

int main() { 
    printAndLog(std::string("hello, world!\n")); 
} 

Wenn Sie den Namen einer Variable verwenden, die Ausdruck-Typ ist L-Wert (? Glvalue); Die R wertigkeit wird verworfen. Ansonsten hätten wir im obigen Beispiel text zu print() verloren. Stattdessen müssen wir explizit sein, wenn wir unsere rvalue verhalten soll, wie man:

template<typename T> 
void printAndLog(T&& text) { 
    print(text); 
    log(std::forward<T>(text)); // if text is an rvalue, give it up. 
} 

--- --- Bearbeiten

I verwendet std::forward weil T1&& und T2&& Universal-Referenzen sind, nicht rvalue Referenzen . https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers

+0

Ich verstehe nicht, warum t2 lvalue ist, der Typ von t2 ist "int &&", was wie eine rvalue-Referenz aussieht. – Charles0429

+0

@ Charles0429 t2 hat einen Namen, du kannst seine Adresse nehmen, also ist es ein Lvalue. Die Tatsache, dass es an rvalue binden kann, bedeutet nicht, dass es sich um einen rvalue handelt. – Amadeus

+0

@ Charles0429 Siehe Bearbeiten. – kfsone