2015-07-22 11 views
5

Ho la seguente funzione diCome passare un riferimento di runtime del C++ a una cattura di una lambda?

template<class Function> 
void f(Function&& g) { 
    h(..., [&g](){g();}); 
} 

E 'una funzione f accettare una funzione, un lambda o un funtore come argomento. Al suo interno chiama la funzione h a cui passo un lambda come argomento che sta chiamando g e riceve g tramite cattura.

  1. Devo passare g o &g nel campo cattura del lambda?
  2. Il funtore verrà copiato con il codice sopra riportato?
+1

Normalmente oggetti funzione simili sono passati per valore. Copiarli dovrebbe essere estremamente economico. Se i tuoi oggetti non sono così, probabilmente stai facendo qualcosa che non è del tutto corretto. –

risposta

2

Se catturare g per riferimento, vale a dire, con la sintassi &g mostrato nel frammento, nessuna copia verrà eseguita. Questo è il modo preferito. Dovresti copiare solo se il lambda potrebbe essere chiamato dopo i termini f, che potenzialmente implica la distruzione dell'oggetto a cui si riferisce g.
In tal caso, l'inoltro potrebbe essere più conveniente però:

template<class Function> 
void f(Function&& g) { 
    h(…, [g=std::forward<Function>(g)] {g();}); 
} 
+2

Si noti che qui si esegue una copia/spostamento dell'originale 'g'. vedere [perfettamente-catturare-a-perfetto-forwarder-universal-reference-in-a-lambda] (http://stackoverflow.com/questions/31410209/perfettamente-concessionario-perfetto-perwarder-universal-reference-in- -a-lambda/31410880 # 31410880) – Jarod42

+2

@ Jarod42 Questa era la mia intenzione. – Columbo

+1

Vedere la risposta di @ Dieter se si ha bisogno di una soluzione equivalente che funzioni con C++ 11 – chmike

1

Si sta costruendo un lambda che non accetta argomenti e non restituisce nulla. Ma hai già un tale functor: g!. Si dovrebbe solo avanti esso:

template<class Function> 
void f(Function&& g) { 
    h(..., std::forward<Function>(g)); 
} 
+2

Sospetto che l'OP lo abbia appena accorciato, e in realtà il lambda fa di più. – Ishamael

+4

@Ishamael Quindi OP dovrebbe mettere ciò che l'OP vuole fare nella domanda in modo che non debba indovinare. – Barry

+1

Come ha detto @Ishamael, ho tolto il codice alla sua forma più semplice. Il lambda fa molto di più che chiamare 'g()' e 'g()' ha argomenti e restituisce un risultato. Hai ragione @Barry, avrei dovuto renderlo esplicito in modo che il lambda non sia ottimizzato nelle risposte. – chmike

1

si potrebbe fare questo:

template<class Function> 
void f(Function&& g) { 
    Function f(std::move(g)); 
    int additional = 0; 
    h(..., [&f, additional](){f(additional);}); 
} 
+1

Questa risposta ha il vantaggio di lavorare con C++ 11. La risposta di @Columbo richiede C++ 14. Ho scelto la sua risposta come risposta valida perché è il nuovo modo standard per farlo. Ma userò la tua risposta finché non passerò a C++ 14. Il tuo contributo è stato utile. – chmike

+0

AFAICS, in questo modo non ha alcun vantaggio rispetto all'approccio originale di @chmikes. Prima di tutto, ti "muovi" quando dovresti "avanzare". In secondo luogo, 'f' viene catturato per riferimento e la sua durata non supera' g', quindi in realtà 'f' è superfluo. – Columbo

+0

@columbo Apparentemente il mio compilatore (4.9.2) richiede che 'f' sia passato per riferimento. Questo codice funziona. Non sono sicuro della differenza che farebbe usare 'forward'. – chmike

Problemi correlati