2012-03-08 20 views
48

Quando provo e compilare il codice (VS2010) Sto ottenendo il seguente errore: error C3499: a lambda that has been specified to have a void return type cannot return a valueesplicita ritorno Tipo di Lambda

void DataFile::removeComments() 
{ 
    string::const_iterator start, end; 
    boost::regex expression("^\\s?#"); 
    boost::match_results<std::string::const_iterator> what; 
    boost::match_flag_type flags = boost::match_default; 
    // Look for lines that either start with a hash (#) 
    // or have nothing but white-space preceeding the hash symbol 
    remove_if(rawLines.begin(), rawLines.end(), [&expression, &start, &end, &what, &flags](const string& line) 
    { 
    start = line.begin(); 
    end = line.end(); 
    bool temp = boost::regex_search(start, end, what, expression, flags); 
    return temp; 
    }); 
} 

Come ho fatto a specificare che il lambda ha un tipo di ritorno 'vuoto'. Inoltre, come posso specificare che il lambda ha il tipo di ritorno 'bool'?

UPDATE

I seguenti compila. Qualcuno può dirmi perché questo compila e l'altro no?

void DataFile::removeComments() 
{ 
    boost::regex expression("^(\\s+)?#"); 
    boost::match_results<std::string::const_iterator> what; 
    boost::match_flag_type flags = boost::match_default; 
    // Look for lines that either start with a hash (#) 
    // or have nothing but white-space preceeding the hash symbol 
    rawLines.erase(remove_if(rawLines.begin(), rawLines.end(), [&expression, &what, &flags](const string& line) 
    { return boost::regex_search(line.begin(), line.end(), what, expression, flags); })); 
} 
+4

È possibile specificare esplicitamente con '->', per esempio '[&] (double d) -> double {// ...' – Flexo

+2

Ti consiglierei di catturare solo implicitamente le variabili di cui hai bisogno (solo '[&] ...'), come quello che hai attualmente è inutilmente prolisso. – Xeo

+0

@Xeo puoi dirmi perché è prolisso? Ho bisogno di cosa, espressione e bandiere nel lambda e questo è ciò che ho catturato. Che cosa potrei tagliare? – Ryan

risposta

114

È possibile specificare in modo esplicito il tipo di ritorno di un lambda utilizzando -> Type dopo l'elenco argomenti:

[]() -> Type { } 

Tuttavia, se un lambda ha una dichiarazione e questa affermazione è una dichiarazione di ritorno (e restituisce un'espressione), il compilatore può dedurre il tipo restituito dal tipo di quella espressione restituita. Hai più istruzioni nel tuo lambda, quindi non deduce il tipo.

+3

il compilatore può farlo, ma lo standard gli impedisce di farlo. –

+7

-1: questo non è un bug del compilatore. Lo standard è molto chiaro su questo: la sezione 5.1.2, paragrafo 4 stabilisce come viene effettuata la detrazione e in quali condizioni si trova. –

+2

@NicolBolas corretto. –

9

Il tipo di ritorno di un lambda può dedurre, ma solo quando v'è esattamente una dichiarazione, e questa affermazione è una dichiarazione return che restituisce un'espressione (una lista di inizializzazione non è espressione, per esempio). Se hai un lambda multi-statement, il tipo di reso è considerato nullo.

Pertanto, si dovrebbe fare questo:

remove_if(rawLines.begin(), rawLines.end(), [&expression, &start, &end, &what, &flags](const string& line) -> bool 
    { 
    start = line.begin(); 
    end = line.end(); 
    bool temp = boost::regex_search(start, end, what, expression, flags); 
    return temp; 
    }) 

Ma in realtà, la tua seconda espressione è molto più leggibile.

+0

Bel esempio; nitpick: alla tua funzione manca la chiamata ');' alla fine? – kevinarpe

2

È possibile avere più di un economico quando ancora tornare:

[]() -> your_type {return (
     your_statement, 
     even_more_statement = just_add_comma, 
     return_value);} 

http://www.cplusplus.com/doc/tutorial/operators/#comma

+2

virgola è un operatore rivoltante. confonde le persone che non sono consapevoli della sua esistenza o del livello di precedenza. non c'è mai un uso valido o imo. può sempre essere evitato con più funzioni o altro codice meglio organizzato. – jheriko

+0

@jheriko d'accordo, l'esistenza della mia risposta è solo per coloro che vogliono davvero una soluzione one-liner indipendente XD (è ancora una riga, giusto?). La virgola non è davvero evidente, e nessuno avrebbe mai messo l'intero metodo principale in questa forma. – Valen

+1

certo, stai dando una risposta valida, io non sono solo un fan di fare mai qualsiasi cosa per incoraggiare o anche dimostrare cattive pratiche. una volta che le persone imparano che la virgola è un operatore, è un conto alla rovescia fino a quando non iniziano ad abusarne e una più lunga finché non imparano meglio. :) – jheriko

Problemi correlati