2016-04-19 16 views
5

Questo è un errore piuttosto strano per me. Controllare il codice qui sotto:Nessun errore di funzione membro corrispondente nell'espressione lambda?

void test(void){ 
    vector<string> v; 
    v.push_back("hello"); 
    auto fn=[=](){ 
     v.push_back("world"); 
    }; 
} 

Il primo metodo push_back superato la compilazione ma il secondo non è riuscito, ottenendo l'errore:

Error:no matching member function for call to 'push_back'

La nota compilatore è:

**Note:(687, 36) candidate function not viable: 'this' argument has type 'const vector' (aka 'const vector, allocator > >')

Ma il metodo non è contrassegnato const**.
Beh, non sto usando alcun argomento const e non riesco a capire cosa stia cercando di dirmi il compilatore. Qualcuno potrebbe aiutarmi?

risposta

10

Le funzioni membro operatore chiamata lambda sono const per impostazione predefinita. Se si desidera un operatore di call mutevole, dire mutable:

auto fn = [=]() mutable { 
//    ^^^^^^^ 
    v.push_back("world"); 
}; 

Avere const siano le forze di default di essere esplicita circa il fatto che si intende catturare un copia del vettore e mutano quella copia, piuttosto che il vettore originale v.

Per contro, le variabili che vengono catturati per riferimento possono essere mutati da funzioni membro const qualificati:

auto fn = [&]() { 
//  ^^^ 
    v.push_back("world"); // modifies original "V"! 
}; 

(Questo è essenzialmente perché const T è uguale T quando T = U &; ci sono "continui riferimenti . "in C++)

+1

Probabilmente si desidera acquisire anche per riferimento. – NathanOliver

+3

@NathanOliver: non "bene", ma piuttosto "invece". –

+0

Ah si. Invece, in effetti, – NathanOliver

4

cattura per valore è const usare la parola mutable (non cambia il vettore originale):

auto fn = [=]() mutable { 
    v.push_back("world"); 
}; 

o con riferimento (cambia il vettore originale):

auto fn = [&]() { 
    v.push_back("world"); 
}; 
0

A causa del tag C++14 e per amor di completezza, vorrei citare anche la lista inizializzazione come soluzione alternativa:

[&vec = v](){ vec.push_back("world") }; 

Se si desidera catturare dalla copia anziché per riferimento:

[vec = v]() mutable { vec.push_back("world") }; 

Gli elenchi di inizializzatori come (diciamolo) il metodo di acquisizione sono disponibili dal C++14, come già menzionato.

Problemi correlati