Zastanawiam się, czy można napisać funkcję zwracającą funkcję lambda w C ++ 11. Oczywiście problemem jest zadeklarowanie takiej funkcji. Każda lambda ma typ, ale tego typu nie można wyrazić w C ++. Myślę, że to nie zadziała:
auto retFun() -> decltype ([](int x) -> int)
{
return [](int x) { return x; }
}
Ani to:
int(int) retFun();
Nie jestem świadomy żadnych automatycznych konwersji z lambd na, powiedzmy, wskaźników do funkcji lub podobnych. Czy jedynym rozwiązaniem jest ręczne tworzenie obiektu funkcji i zwracanie go?
decltype
nie jest taka sama jak w treści funkcji i dlatego ma inny typ (nawet jeśli uwzględnisz instrukcję return)decltype([](){})
lubsizeof([]() {})
jest źle sformułowane, bez względu na to, gdzie to piszesz.Odpowiedzi:
Nie potrzebujesz ręcznie
std::function
tworzonego obiektu funkcyjnego, po prostu użyj , na który funkcje lambda są konwertowane:Ten przykład zwraca funkcję tożsamości w postaci liczby całkowitej:
std::function<int (int)> retFun() { return [](int x) { return x; }; }
źródło
std::function
.std::function
wykorzystuje wymazywanie typów, co może oznaczać koszt wykonania wirtualnego wywołania funkcji podczas wywoływaniastd::function
. Coś, o czym należy pamiętać, jeśli zwrócona funkcja będzie używana w ścisłej pętli wewnętrznej lub w innym kontekście, w którym niewielka nieefektywność ma znaczenie.W tym prostym przykładzie nie potrzebujesz
std::function
.Od standardu §5.1.2 / 6:
Ponieważ twoja funkcja nie ma przechwytywania, oznacza to, że lambda można przekonwertować na wskaźnik do funkcji typu
int (*)(int)
:typedef int (*identity_t)(int); // works with gcc identity_t retFun() { return [](int x) { return x; }; }
Tak rozumiem, popraw mnie, jeśli się mylę.
źródło
Możesz zwrócić funkcję lambda z innej funkcji lambda, ponieważ nie powinieneś jawnie określać zwracanego typu funkcji lambda. Po prostu napisz coś takiego w zakresie globalnym:
auto retFun = []() { return [](int x) {return x;}; };
źródło
Chociaż pytanie dotyczy konkretnie C ++ 11, ze względu na innych, którzy się na to natkną i mają dostęp do kompilatora C ++ 14, C ++ 14 pozwala teraz na wywnioskowane typy zwracane dla zwykłych funkcji. Tak więc przykład w pytaniu można dostosować tak, aby działał zgodnie z oczekiwaniami, po prostu upuszczając
-> decltype
klauzulę ... po liście parametrów funkcji:auto retFun() { return [](int x) { return x; } }
Należy jednak pamiętać, że to nie zadziała, jeśli
return <lambda>;
w funkcji pojawi się więcej niż jeden . Dzieje się tak, ponieważ ograniczenie dotyczące odliczania typu zwracanego polega na tym, że wszystkie instrukcje return muszą zwracać wyrażenia tego samego typu, ale każdy obiekt lambda otrzymuje od kompilatora swój własny, unikalny typ, więcreturn <lambda>;
każde wyrażenie będzie miało inny typ.źródło
auto retFun() { return [](auto const& x) { return x; }; }
Powinieneś napisać tak:
auto returnFunction = [](int x){ return [&x](){ return x; }(); };
aby otrzymać zwrot jako funkcję i użyj go w ten sposób:
int val = returnFunction(someNumber);
źródło
Jeśli nie masz C ++ 11 i uruchamiasz swój kod C ++ na przykład na mikrokontrolerach. Możesz zwrócić void pointer, a następnie wykonać rzut.
void* functionThatReturnsLambda() { void(*someMethod)(); // your lambda someMethod = []() { // code of lambda }; return someMethod; } int main(int argc, char* argv[]) { void* myLambdaRaw = functionThatReturnsLambda(); // cast it auto myLambda = (void(*)())myLambdaRaw; // execute lambda myLambda(); }
źródło