2017-02-22 2 views
3

Ich versuche derzeit herauszufinden, wie genau perfekte Weiterleitung funktioniert. Ich habe ein Stück Beispielcode geschrieben, soweit ich das perfekte Weiterleitung geschieht wissen, wie es sein soll ist:Perfect Fowarding und die Verwendung von Std :: vorwärts <T>

void whatIsIt(std::vector<int>&& variable) 
{ 
    std::cout << "rvalue" << std::endl; 
} 

void whatIsIt(std::vector<int>& variable) 
{ 
    std::cout << "lvalue" << std::endl; 
} 

template <class T> 
void performPerfectForwarding(T&& variable) 
{ 
    whatIsIt(std::forward<T>(variable)); 
} 

int main(int argc, char** argv) 
{ 
    std::vector<int> lvalue; 
    performPerfectForwarding(lvalue); 
    performPerfectForwarding(std::move(lvalue)); 

    return 0; 
} 

Aufruf der Funktion performPerfectForwarding mit einem L-Wert macht es die entsprechenden Überlastung der whatIsIt nennen und das gleiche gilt für mit einem rvalue aufrufen. Folglich wird durch diesen Code die Ausgabe erzeugt wird:

lvalue 
rvalue 

Allerdings war ich mich zu fragen, was die folgenden Versionen der Funktion performPerfectForwarding tun würde:

1.

template <class T> 
void performPerfectForwarding(T& variable) 
{ 
    whatIsIt(std::forward<T>(variable)); 
} 

2.

template <class T> 
void performPerfectForwarding(T variable) 
{ 
    whatIsIt(std::forward<T>(variable)); 
} 

Beide ausgeben:

rvalue 
rvalue 

Jetzt sind meine Fragen: Was würden diese beiden alternativen Versionen tun und würden sie in jedem möglichen Kontext sinnvoll sein? Wie gelten die Regeln für den kollabierenden Verweis in diesen Fällen, verglichen mit der Anwendung in der oben genannten "richtigen" Version?

Antwort

8
template <class T> 
void performPerfectForwarding(T& variable) 
{ 
    whatIsIt(std::forward<T>(variable)); 
} 

Wenn variable ist kein Forwarding-Referenz, T als T auch für lvalues ​​abgeleitet(in constrast als T& abgeleitet wird). Dies deshalb wirft variable auf ein rvalue Referenz, denn:

forward<T> -> T&& 
forward<T&> -> T& 
forward<T&&> -> T&& 

template <class T> 
void performPerfectForwarding(T variable) 
{ 
    whatIsIt(std::forward<T>(variable)); 
} 

Gleiche Überlegungen gelten hier. T kann nie ein lvalue Referenz hier sein, so forward wird immer auf rvalue Referenz.


Was würden diese zwei alternativen Versionen zu tun und würden sie Sinn in jedem möglichen Zusammenhang zu machen?

glaube ich so nicht, weil Ihr forward im Grunde ein move ist.


Wie die Referenz gelten Kollabieren Regeln in diesen Fällen im Vergleich zu, wie sie in der oben erwähnten „richtigen“ Version anwenden?

Die Regeln werden hier wie gewohnt angewendet.Denken Sie daran:

& & -> & 
& && -> & 
&& & -> & 
&& && -> && 

In beiden Fällen gibt es keine Möglichkeit hat zu haben variable eine && werden.

+0

Vielen Dank für die knappe Antwort. Es gibt jedoch noch eine Sache, die ich mir selbst stelle. Wenn ich meine Funktion 'perfectForwarding (T &&)' mit einem Lvalue anrufe, warum wird T als ein Referenztyp ('T &') abgeleitet. Die kollabierenden Regeln würden mir einfach '&&' (von der Funktionssignatur) geben, was zu '&&' führt, wenn es zusammengelegt wird. Oder würde es tatsächlich zu "& &&?" Tut mir leid, wenn ich ein bisschen verwirrt darüber bin, wie Referenzen in Kombination mit Vorlagen funktionieren. Nur wenn ich eine Funktion 'doSth (int & parameter)' hätte, dann hätte der Parameter immer noch den Typ 'int', nicht den Typ 'int & '. – user1488118

+0

Oder mit anderen Worten: Wenn ich 'perfectiveForwarding (T & # 8220;) ausführen würde und dies mit einem Lvalue aufrufen würde, würde 'T' als 'T' nicht als 'T &' innerhalb der Funktion ausgewertet werden. Ist das also eine verrückte Sonderregel, die nur für diese "Universalreferenzen" ('T &&') gilt? – user1488118

+1

* 'Also ist das eine verrückte Sonderregel, die nur für diese "universellen Referenzen" gilt? * - ziemlich genau. Siehe [cppreference/template argument deduction/deduction von einem Funktionsaufruf/4] (http://en.cppreference.com/w/cpp/language/template_argument_deduction#Deduction_from_a_function_call). –

Verwandte Themen