Kiedy próbuję skompilować ten kod (VS2010), pojawia się następujący błąd:
error C3499: a lambda that has been specified to have a void return type cannot return a value
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;
});
}
Jak określiłem, że lambda ma typ powrotu „void”. Co więcej, jak określić, że lambda ma zwracany typ „bool”?
AKTUALIZACJA
Następujące kompilacje. Czy ktoś może mi powiedzieć, dlaczego to się kompiluje, a drugie nie?
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); }));
}
->
, np.[&](double d) -> double { //...
[&]...
), ponieważ to, co obecnie masz, jest niepotrzebnie rozwlekłe.[&expression, &start, &end, &what, &flags]...
(twój) vs[&]...
(mój). Teraz powiedz mi, kto jest bardziej szczegółowy. ;)[&]
mówi lambdzie, aby przechwyciła wszystko, czego używasz wewnątrz ciała lambda, przez odniesienie. Nazywa się to „domyślnym przechwytywaniem”. Drugi jest[=]
i będzie przechwytywany przez kopię.Odpowiedzi:
Możesz jawnie określić zwracany typ lambdy, używając
-> Type
po liście argumentów:Jeśli jednak lambda ma jedną instrukcję, a ta instrukcja jest instrukcją powrotu (i zwraca wyrażenie), kompilator może wydedukować typ zwracania na podstawie typu tego zwróconego wyrażenia. Masz wiele instrukcji w swojej lambdzie, więc nie dedukuje typu.
źródło
return nullptr;
może rzucać kluczem w dedukcji typu, nawet jeśli jest to poprawne, ponieważ w przeciwnym razie zwracany jest typ wskaźnika.Zwracany typ lambda (w C ++ 11) można wywnioskować, ale tylko wtedy, gdy istnieje dokładnie jedna instrukcja, a ta instrukcja jest
return
instrukcją, która zwraca wyrażenie (na przykład lista inicjalizacyjna nie jest wyrażeniem). Jeśli masz lambdę składającą się z wielu instrukcji, zakłada się, że zwracany typ jest nieważny.Dlatego powinieneś to zrobić:
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; })
Ale tak naprawdę twoje drugie wyrażenie jest o wiele bardziej czytelne.
źródło
);
na końcu brakuje wywołania funkcji ?Możesz mieć więcej niż jedną instrukcję, gdy nadal zwracasz:
[]() -> your_type {return ( your_statement, even_more_statement = just_add_comma, return_value);}
http://www.cplusplus.com/doc/tutorial/operators/#comma
źródło