2012-06-21 15 views
11

Perché definizione di std :: funzione <> :: operator() nello standard C++ è:C++ 11 std :: funzione e spedizioni perfetta

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

e non

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

?

Si potrebbe pensare che per inoltrare correttamente i parametri, è necessario il & & e quindi utilizzare std::forward<ArgTypes>... nel corpo della funzione quando si inoltra la chiamata?

ho parzialmente reimplementato std :: funzione per testare questo e ho scoperto che se uso il & &, ottengo "non può legarsi 'xxx' lvalue a 'xxx & &'" da g ++ quando provo poi passare parametri per valore per operatore(). Ho pensato di avere una conoscenza sufficiente dei concetti di rvalore/inoltro, ma non riesco ancora a eludere questo punto. Cosa mi manca?

risposta

13

L'inoltro perfetto funziona solo quando la funzione stessa (in questo caso operator()) è basata su modello e gli argomenti del modello sono dedotti. Per std::function, si ottengono i tipi di argomento operator() dai parametri del modello della classe , il che significa che non verranno mai dedotti da alcun argomento.

L'intero trucco dietro l'inoltro perfetto è la parte di deduzione argomento modello, che, insieme al riferimento collassante, è l'inoltro perfetto.

Qui mi collegherò comodamente a my other answer about std::forward qui, dove spiego come l'inoltro perfetto (e std::forward) funziona.

Nota che lo operator()std::function non ha bisogno di inoltro perfetto, poiché l'utente stesso decide quali dovrebbero essere i parametri. Questo è anche il motivo per cui non puoi semplicemente aggiungere && a operator(); prendi questo esempio:

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

Grazie, tutto ha perfettamente senso ora. – airman

+0

@Xeo, il tuo codice viene compilato correttamente ... http://ideone.com/7TyCB8 Non c'è nessun errore in f (i), puoi spiegare cosa intendi con "// error", o forse sto usando il compilatore sbagliato Grazie. –

+0

@WillBradley: rileggi il commento nella parte superiore di 'main': *** Assume *** che' std :: function :: operator() la firma di 'era in realtà' R (Args && ...) '- questo con, diciamo, 'function ' produce 'void (int &&)' per 'operator()', che ora accetta solo rvalues. – Xeo

Problemi correlati