This answer spiega come spostare-catturare una variabile all'interno di una lambda in C++ 14.Spostamento di una lambda: una volta spostato, acquisito un tipo di solo spostamento, come può essere utilizzato il lambda?
Ma dopo aver spostato un oggetto non copiabile (come ad esempio std::unique_ptr
) all'interno di una lambda, non è possibile copiare la lambda stessa.
Questo andrebbe bene se si potesse spostare lambda, ma ottengo un errore di compilazione quando si cerca di farlo:
using namespace std;
class HasCallback
{
public:
void setCallback(std::function<void(void)>&& f)
{
callback = move(f);
}
std::function<void(void)> callback;
};
int main()
{
auto uniq = make_unique<std::string>("Blah blah blah");
HasCallback hc;
hc.setCallback(
[uniq = move(uniq)](void)
{
std::cout << *uniq << std::endl;
});
hc.callback();
}
Questo produce il seguente errore con g++
(ho tentato di copiare solo la linea pertinente):
error: use of deleted function ‘main()::<lambda()>::<lambda>(const main()::<lambda()>&’
... insinuando, penso, che il mio tentativo di spostare il lambda ha fallito.
clang++
restituisce un errore simile.
Ho provato esplicitamente move
in lambda (anche se è un valore temporaneo), ma ciò non ha aiutato.
MODIFICA: Le risposte seguenti rispondono in modo adeguato agli errori di compilazione prodotti dal codice precedente. Per un approccio alternativo, è sufficiente release
il valore di destinazione del puntatore univoco in un std::shared_ptr
, che può essere copiato da. (Non sto scrivendo questo come una risposta, perché ciò presuppone che si tratti di un problema XY, ma il motivo sottostante per cui unique_ptr
non può essere utilizzato in un lambda che viene convertito in un std::function
è importante da comprendere.)
EDIT 2: In modo abbastanza strano, ho appena realizzato auto_ptr
farebbe davvero la cosa giusta qui (!), Per quanto posso dire. Agisce essenzialmente come unique_ptr
, ma consente la costruzione della copia al posto della costruzione del movimento.
penso setCallback dovrebbe ottenere parametro per valore piuttosto che di riferimento rvalue, mi sbaglio? – Slava
@Slava Questo è ciò che avevo originariamente, ma ha dato lo stesso errore. Pensavo che prendere il riferimento di valore avrebbe permesso (/ forzare) il lambda di essere costruito con il movimento, ma non sembra essere il caso. –