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