Интересно, можно ли написать функцию, возвращающую лямбда-функцию на C ++ 11. Конечно, одна проблема - как объявить такую функцию. У каждой лямбды есть тип, но этот тип нельзя выразить в C ++. Я не думаю, что это сработает:
auto retFun() -> decltype ([](int x) -> int)
{
return [](int x) { return x; }
}
Ни это:
int(int) retFun();
Мне не известны какие-либо автоматические преобразования лямбда-выражений, скажем, в указатели на функции или что-то подобное. Единственное решение - создать объект функции вручную и вернуть его?
decltype
теле функции не такая же, как в теле функции, и поэтому имеет другой тип (даже если вы включили оператор возврата)decltype([](){})
илиsizeof([]() {})
плохо сформирован, где бы вы это не написали.Ответы:
Вам не нужен объект функции ручной работы, просто используйте
std::function
, в какие лямбда-функции можно преобразовать:Этот пример возвращает целочисленную функцию идентификации:
std::function<int (int)> retFun() { return [](int x) { return x; }; }
источник
std::function
.std::function
используется стирание типа, что может означать стоимость вызова виртуальной функции при вызовеstd::function
. Что-то, о чем нужно знать, будет ли возвращенная функция использоваться в жестком внутреннем цикле или другом контексте, где имеет значение небольшая неэффективность.Для этого простого примера вам не нужно
std::function
.Из стандартного §5.1.2 / 6:
Поскольку ваша функция не имеет захвата, это означает, что лямбда может быть преобразована в указатель на функцию типа
int (*)(int)
:typedef int (*identity_t)(int); // works with gcc identity_t retFun() { return [](int x) { return x; }; }
Это мое понимание, поправьте меня, если я ошибаюсь.
источник
Вы можете вернуть лямбда-функцию из другой лямбда-функции, так как вы не должны явно указывать тип возврата лямбда-функции. Просто напишите что-нибудь подобное в глобальной области:
auto retFun = []() { return [](int x) {return x;}; };
источник
Хотя вопрос конкретно касается C ++ 11, для других, кто наткнется на это и имеет доступ к компилятору C ++ 14, C ++ 14 теперь позволяет выводить типы возвращаемого значения для обычных функций. Таким образом, пример в вопросе можно настроить так, чтобы он работал по желанию, просто отбросив предложение
-> decltype
... после списка параметров функции:auto retFun() { return [](int x) { return x; } }
Учтите, однако, что это не сработает, если
return <lambda>;
в функции указано более одного . Это связано с тем, что ограничение на вывод типа возвращаемого значения состоит в том, что все операторы return должны возвращать выражения одного и того же типа, но каждому лямбда-объекту компилятор присваивает свой собственный уникальный тип, поэтомуreturn <lambda>;
каждое выражение будет иметь другой тип.источник
auto retFun() { return [](auto const& x) { return x; }; }
Вы должны написать так:
auto returnFunction = [](int x){ return [&x](){ return x; }(); };
чтобы получить доход как функцию, и используйте его как:
int val = returnFunction(someNumber);
источник
Если у вас нет C ++ 11 и, например, вы запускаете код C ++ на микроконтроллерах. Вы можете вернуть указатель void, а затем выполнить приведение.
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(); }
источник