2012-06-21 9 views
11

Warum Definition von std :: function <> :: operator() im ++ Standard C:C++ 11 std :: Funktion und perfektes Forwarding

R operator()(ArgTypes...) const; 

und nicht

R operator()(ArgTypes&&...) const; 

?

Man würde denken, dass richtig vorwärts Parameter, müssen wir die & & und dann std::forward<ArgTypes>... im Funktionskörper verwenden, wenn die Anrufumleitung?

ich teilweise std :: Funktion zu testen, diese neu implementiert und ich fand heraus, dass, wenn ich die & & verwenden, erhalte ich „nicht binden kann‚xxx‘L-Wert zu‚xxx & &‘“ von g ++, wenn ich später versuchen zu passieren Parameter nach Wert für operator(). Ich dachte, dass ich die rvalue/forwarding Konzepte genug verstanden habe, aber ich kann diesen Punkt noch nicht verstehen. Was vermisse ich?

Antwort

13

Perfect Forwarding funktioniert nur, wenn die Funktion selbst (in diesem Fall operator()) templated ist und die Template-Argumente abgeleitet werden. Für std::function erhalten Sie die operator() Argumenttypen aus den Vorlagenparametern der Klasse selbst, was bedeutet, dass sie nie von irgendwelchen Argumenten abgeleitet werden.

Der ganze Trick hinter perfekter Weiterleitung ist der Template-Argument-Deduktionsteil, der zusammen mit dem Referenz-Collapsing die perfekte Weiterleitung ist.

Ich werde einfach nur zu my other answer about std::forward hier verlinken, wo ich erkläre, wie perfekt Weiterleitung (und std::forward) funktioniert.

Beachten Sie, dass std::functionoperator() keine perfekte Weiterleitung benötigt, da der Benutzer selbst entscheidet, was die Parameter sein sollen. Dies ist auch der Grund, warum Sie nicht einfach && zu operator() hinzufügen können; Nimm dieses Beispiel:

void foo(int){} 

int main(){ 
    // assume 'std::function' uses 'ArgTypes&&...' in 'operator()' 
    std::function<void(int)> f(foo); 
    // 'f's 'operator()' will be instantiated as 
    // 'void operator()(int&&)' 
    // which will only accept rvalues 
    int i = 5; 
    f(i); // error 
    f(5); // OK, '5' is an rvalue 
} 
+0

Danke, alles macht jetzt vollkommen Sinn. – airman

+0

@Xeo, dein Code kompiliert korrekt ... http://ideone.com/7TyCB8 Es gibt keinen Fehler bei f (i), kannst du erklären, was du mit "// error" meinst, oder vielleicht benutze ich den falscher Compiler. Vielen Dank. –

+0

@WillBradley: Lesen Sie den Kommentar an der Spitze von 'main': *** Nehmen Sie an *** dass' std :: function :: operator() ''s Unterschrift war eigentlich' R (Args && ...) '- dies würde, zum Beispiel, mit der Funktion '' void (int &&) 'für den' operator() 'erzeugen, der jetzt nur rvalues ​​akzeptiert. – Xeo

Verwandte Themen