2015-07-02 12 views
13

Sto costruendo una funzione lambda che richiede l'accesso a un discreto numero di variabili nel contesto.Passaggio per riferimento costante nella lista di cattura lambda

const double defaultAmount = [&]{ 
    /*ToDo*/ 
}(); 

Preferirei non uso [=] nella lista come io non voglio un sacco di copie di valore da effettuare.

Sono preoccupato per la stabilità del programma se utilizzo [&] poiché non desidero che lambda modifichi il set di acquisizione.

Posso passare con riferimento const? [const &] non funziona.

Forse un buon compilatore ottimizza le copie del valore, quindi è preferibile [=].

+0

Sono queste variabili locali o membri? Che compilatore usi? – MikeMB

+0

Un po 'di entrambi. Sto usando MSVC2012 e dovrei scrivere un codice che compili con i nuovi g ++. –

risposta

11

È possibile creare e catturare i riferimenti const esplicitamente:

lista
int x = 42; 
const int& rx = x; 
auto l = [&rx]() { 
    x = 5; // error: 'x' is not captured 
    rx = 5; // error: assignment of read-only reference 'rx' 
}; 
2

Purtroppo la grammatica C++ 11 non lo consente, quindi no.

+0

Se la subroutine richiede "un buon numero di variabili nel contesto", fare una funzione corretta e passarle tutte è probabilmente esattamente ciò che l'OP sta tentando di evitare. – Angew

2

È possibile catturare un costante riferimento a un oggetto, non un oggetto in sé:

A a; 
const A& ref_a = a; 

const double defaultAmount = [&]{ 
    ref_a.smth(); 
}(); 
7

La cattura è limitata a ciò che può essere catturato; fondamentalmente in base al valore o al riferimento (denominato o predefinito), il puntatore this e nulla.

dal cppreference;

cattura-list - un elenco separato da virgole di zero o più catture, opzionalmente a cominciare da un cattura-default. elenco cattura può essere passato come segue (vedi sotto per la descrizione dettagliata):

  • [a,&b] dove a viene catturata in valore e b viene catturato per riferimento.
  • [this] cattura il puntatore this dal valore
  • [&] cattura tutte le variabili automatiche ODR-utilizzati nel corpo del lambda con riferimento
  • [=] cattura tutte le variabili automatiche ODR utilizzato nel corpo di il lambda per valore
  • [] non cattura nulla

È possibile creare locale const& per tutti gli oggetti che si desidera catturare e utilizzare quelli in lambda.

#include <iostream> 

using namespace std; 

int main() 
{ 
    int a = 5; 
    const int& refa = a; 
    const int b = [&]() -> int { 
     //refa = 10; // attempts to modify this fail 
     return refa; 
    }(); 
    cout << a << " " << b << endl; 
} 

L'acquisizione può essere per tutti i riferimenti o un elenco esplicito di ciò che è richiesto;

const int b = [&refa]() 

Un'altra alternativa è non acquisire affatto le variabili locali. Quindi crei un lambda che accetta come argomenti le variabili che ti servono. Può essere più difficile man mano che aumenta il conteggio delle variabili locali, ma si ha un maggiore controllo su come lambda accetta i suoi argomenti ed è in grado di utilizzare i dati.

auto lambda = [](const int& refa /*, ...*/) { */...*/ } 
lambda(...); 
Problemi correlati