Каков тип функции лямбды?

В C++ 0x, я задаюсь вопросом, что тип имеет функцию лямбды. Конкретно:

#include<iostream>

type1 foo(int x){
 return [x](int y)->int{return x * y;};
}

int main(){

 std::cout<<foo(3)(4);//would output 12

 type2 bar = foo(5);
 std::cout<<bar(6);//would output 30
 return 0;
}

Чем я должен заменить type1/type2 заставить вышеупомянутое работать? Надо надеяться, Вы видите то, что я пытаюсь выполнить, поэтому даже если это не возможно прямой заменой type1 и type2, возможно, можно вести меня в правильном направлении.

Другими словами:

  • Как я могу заставить функцию возвращать анонимную функцию?
  • Как я могу присвоить анонимную функцию переменной?

Спасибо!

Править: Я компилирую с Visual Studio 2010

8
задан Cam 1 July 2010 в 20:10
поделиться

2 ответа

Вы никогда не сможете узнать тип лямбда-функции, потому что логически происходит следующее: компилятор создает (локальный) класс с перегруженным оператором вызова функции, а лексическое закрытие представлено членами данных этого (локального) класса. Вот что логически происходит для лямбда-функции типа:

auto foo = [](int x, int y) { return x + y; };

Компилятор логически делает следующее:

struct CompilerGeneratedName { void operator()(int x, int y) const { return x + y; } };
CompilerGeneratedName foo;

Поскольку компилятор генерирует (локальный) класс, он генерирует имя, и поэтому вы никогда не можете явно написать тип, вы можете только вывести тип из вычитания типов аргументов шаблонных функций или используя auto/decltype.

Кроме того, закрытия C++0x статически распределяются, поэтому вы не сможете безопасно вернуть необработанное закрытие C++0x.

Тем не менее, есть несколько способов добиться этого, первый из которых более гибкий и поддерживает лямбда-функции, которые захватывают лексические диапазоны. Используйте std::function, если у вас есть лямбда-функция, которая не захватывает ничего из внешней области видимости, то вы можете использовать указатели функций, но это преобразование больше подходит для работы с устаревшим кодом.

Итак, в основном вы хотите получить следующее:

std::function< int (int) > foo(int x)
{
    return [x](int y)->int{return x * y;};
}

Причина, по которой я продолжал говорить логически, заключается в том, что именно так boost::lambda работает изначально (хотя C++03 не позволяет использовать локальные классы в аргументах шаблонных функций) и именно отсюда возникла идея добавления лямбда-функций, но поскольку теперь это языковая функция, производители компиляторов могут реализовать ее различными и более эффективными способами, например, при захвате всего окружения по ссылке компилятор может просто передать указатель на стек вызовов вместо логического способа, сохраняя при этом логическое представление.

14
ответ дан 5 December 2019 в 08:22
поделиться

From Википедия :

Лямбда-функции - это функциональные объекты зависимого от реализации типа; имя этого типа доступно только компилятору. Если пользователь желает использовать лямбда-функцию в качестве параметра, тип должен быть типом шаблона, или он должен создать std :: function для захвата значения лямбда.

VC10 компилирует это

//Beware, brain-compiled code ahead!
#include<iostream>
#include<functional>

std::function<int(int)> foo(int x)
{
    return [x](int y)->int{return x * y;};
}

int main(){

    std::cout<<foo(3)(4) << '\n';

    auto bar = foo(5);
    std::cout<<bar(6) << '\n';

    return 0;
}

и печатает

12
30
6
ответ дан 5 December 2019 в 08:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: