2011-12-12 16 views
8

Dire che ho una sorta di tipo incartamento una funzione, forse una funzione lambda:Cosa succede quando viene assegnato un tipo contenente un lambda?

template<typename Function> 
    struct my_struct 
{ 
    Function f; 

    my_struct(const Function &f) : f(f) {} 
}; 

Cosa succede quando viene assegnato un esempio di questo tipo? La mia comprensione è che i lambda sono immutabili e hanno eliminato gli operatori di assegnazione.

Tuttavia, quando assegno a un oggetto di questo tipo nel frammento di codice di seguito, nessun errore viene emesso:

// a structure which contains a function; 
// possibly a lambda function 
template<typename Function> 
    struct my_struct 
{ 
    Function f; 

    my_struct(const Function &f) : f(f) {} 

    // XXX adding this assignment operator causes an error 
    //my_struct &operator=(const my_struct &other) 
    //{ 
    // f = other.f; 
    // return *this; 
    //} 
}; 

template<typename Function> 
my_struct<Function> make_struct(const Function &f) 
{ 
    return my_struct<Function>(f); 
} 

int main() 
{ 
    // create some lambda 
    auto lambda = [](int x){return x;}; 

    // make a struct containing a copy of the lambda 
    auto x = make_struct(lambda); 

    // try to assign to the struct, which 
    // presumably assigns to the enclosed lambda 
    x = make_struct(lambda); 

    return 0; 
} 

Aggiungendo l'operatore di assegnazione commentata-out produce un errore, come previsto:

$ g++-4.6 -std=c++0x test.cpp 
test.cpp: In member function ‘my_struct<Function>& my_struct<Function>::operator=(const my_struct<Function>&) [with Function = main()::<lambda(int)>, my_struct<Function> = my_struct<main()::<lambda(int)> >]’: 
test.cpp:34:25: instantiated from here 
test.cpp:13:5: error: use of deleted function ‘main()::<lambda(int)>& main()::<lambda(int)>::operator=(const main()::<lambda(int)>&)’ 
test.cpp:27:18: error: a lambda closure type has a deleted copy assignment operator 

Quindi, è possibile creare tipi assegnabili con variabili membro lambda? Sembra una cosa ragionevole da provare. Prendi in considerazione la combinazione di una lambda con boost::transform_iterator, ad esempio.

+2

Non so ancora molto del trasferimento, ma è possibile che possano essere spostati ma non copiati? Potresti già sapere la risposta a questo, ma non sono a conoscenza di chi si muove, quindi se lo fai, per favore dillo. –

+0

Grazie per l'idea, ma l'introduzione di un operatore di spostamento non sembrava modificare il messaggio di errore. –

risposta

12

Sei vicino. Un lambda ha un costruttore implicito di copie e può avere - a seconda dei valori catturati - un costruttore di mosse implicito. Ha un operatore di assegnazione delle copie cancellato.

In altre parole, è possibile costruirlo, ma non è possibile assegnarlo. Se stai cercando un oggetto funzione generico, si desidera utilizzare std::function<>. Emula funzioni come valori di prima classe.


Si noti che immutabile è diverso da assegnabile. Quando un lambda è chiamato mutevole, significa che il corpo chiamata di funzione può modificare i membri della lambda (cioè, la funzione non è const):

int i = 0; 

auto okay = [=](int x) mutable { i += x; }; 
auto error = [=](int x) { i += x; }; 

Ciascuno di questi è copia-costruibile e non cedibile.

+3

Grazie per la spiegazione. È un compito troppo brutto cancellato - sembra rendere incompatibile lambda con '' 'boost :: transform_iterator''', almeno con la sua attuale implementazione. –

+0

Vedere [questa risposta] (http://stackoverflow.com/a/35412456/554283) per altri espedienti (utilizzando std :: ref, la libreria Boost Fit proposta e la libreria Boost Range Extensions proposta). –

+0

ma come può allora std :: function fare una copia del lambda? –

Problemi correlati