2016-03-01 12 views
5

Il seguente esempio fittizio potrebbe non avere realmente senso nel mondo reale. Ma spiega la domanda. Ho un class Foo con membri firstname e lastname. La funzione ForEachMessage accetta una lambda. Voglio catturare solo il firstname di Foo ma non lastname. Come lo realizzo?Come catturare alcune variabili membro (ma non tutte) di una classe con lambda

#include <iostream> 
#include <vector> 
#include <functional> 
using namespace std; 

vector<string> messagesList; 
void ForEachMessage(function<void(const string&)>callBack) 
{ 
    for (const auto& str : messagesList) { 
     callBack(str); 
    } 
} 

class Foo { 
public: 
    std::string firstname; 
    std::string lastname; 
    void say() { 
     ForEachMessage([this](const std::string& someMessage) 
     { 
      cout << firstname << ": " << someMessage << endl; 
     }); 

     // Error: firstname in capture list doesn't name a variable 
     // ForEachMessage([firstname](const std::string& someMessage) 
     // { 
     // cout << firstname << ": " << someMessage << endl; 
     // }); 

     // Error: expect ',' or ']' in lambda capture list 
     // ForEachMessage([this->firstname](const std::string& someMessage) 
     // { 
     // cout << firstname << ": " << someMessage << endl; 
     // }); 
    } 
}; 

int main(int argc, const char * argv[]) { 
    Foo foo; 
    foo.firstname = "Yuchen"; 
    foo.lastname = "Zhong"; 
    messagesList.push_back("Hello, World!"); 
    messagesList.push_back("Byebye, World!"); 
    foo.say(); 
    return 0; 
} 
+1

"Non funziona" è il minimo descrizione del problema utile nel mondo. – molbdnilo

+0

@molbdnilo, grazie per i commenti. Ho aggiunto anche il messaggio di errore. –

+1

[Correzione rapida] (http://coliru.stacked-crooked.com/a/131b92770d94e458). Mi chiedo se c'è un modo migliore però. –

risposta

5

È possibile utilizzare il C++ 14 chiamato cattura per questo:

ForEachMessage([bla=firstname](const std::string& someMessage) 
    { 
     cout << bla << ": " << someMessage << endl; 
    }); 

(Vedi live) Per evitare una copia, è possibile anche acquisire per riferimento con [&bla=firstname] invece. Per una discussione su come acquisire tramite const&, vedere this question e in particolare this answer.

(Nota:. Il nome locale può, ma non deve essere diverso dal nome del membro)

+0

Ora questo è bello! – Nard

+2

Sembra che potresti anche usare '[& firstname = firstname]' –

+0

@SimonKraemer In effetti, hai battuto la mia modifica di secondi Thx per l'input. –

3

Creare un riferimento al firstname

const std::string& rfn = firstname; 

e catturare il riferimento

ForEachMessage([rfn](const std::string& someMessage) 
{ 
    cout << rfn << ": " << someMessage << endl; 
} 
+0

Grazie per la modifica! – Nard

+0

Oops. Grazie per aver risolto il mio. M ( –

Problemi correlati