С++ 11 lambda как переменная-член?
Можно ли определить лямбда как члены класса?
Например, можно ли переписать пример кода ниже, используя лямбда вместо объекта функции?
struct Foo {
std::function<void()> bar;
};
Я удивляюсь, потому что в качестве аргументов можно передать следующую лямбду:
template<typename Lambda>
void call_lambda(Lambda lambda) // what is the exact type here?
{
lambda();
}
int test_foo() {
call_lambda([]() { std::cout << "lambda calling" << std::endl; });
}
Я понял, что если лямбда может быть передана как аргумент функции, возможно, они также могут быть сохранены как переменная-член.
После большего мастерства я обнаружил, что это работает (но это вроде бессмысленно):
auto say_hello = [](){ std::cout << "Hello"; };
struct Foo {
typedef decltype(say_hello) Bar;
Bar bar;
Foo() : bar(say_hello) {}
};
Ответы
Ответ 1
Шаблоны позволяют без стирания типа, но это:
template<typename T>
struct foo {
T t;
};
template<typename T>
foo<typename std::decay<T>::type>
make_foo(T&& t)
{
return { std::forward<T>(t) };
}
// ...
auto f = make_foo([] { return 42; });
Повторение аргументов, которые все уже выставили: []{}
не является типом, поэтому вы не можете использовать его, например. параметр шаблона, как вы пытаетесь. Использование decltype
также iffy, потому что каждый экземпляр лямбда-выражения является обозначением для отдельного объекта замыкания с уникальным типом. (например, тип f
выше не foo<decltype([] { return 42; })>
.)
Ответ 2
Лямбда просто создает объект функции, поэтому да, вы можете инициализировать член функции с помощью лямбда. Вот пример:
#include <functional>
#include <cmath>
struct Example {
Example() {
lambda = [](double x) { return int(std::round(x)); };
};
std::function<int(double)> lambda;
};
Ответ 3
#include <functional>
struct Foo {
std::function<void()> bar;
};
void hello(const std::string & name) {
std::cout << "Hello " << name << "!" << std::endl;
}
int test_foo() {
Foo f;
f.bar = std::bind(hello, "John");
// Alternatively:
f.bar = []() { hello("John"); };
f.bar();
}
Ответ 4
Немного поздно, но я не видел этого ответа здесь. Если лямбда не имеет аргументов захвата, то она может быть неявно передана указателю на функцию с теми же аргументами и возвращаемыми типами.
Например, следующая программа компилируется и делает то, что вы ожидаете:
struct a {
int (*func)(int, int);
};
int main()
{
a var;
var.func = [](int a, int b) { return a+b; };
}
Конечно, одним из основных преимуществ lambdas является предложение захвата, и как только вы это добавите, тогда этот трюк просто не сработает. Используйте std:: function или шаблон, как было сказано выше.
Ответ 5
", если лямбда может быть передана как аргумент функции, а может быть, также как переменная-член"
Первое - это да, вы можете использовать вывод аргумента шаблона или "авто" для этого. Второй, вероятно, нет, так как вам нужно знать тип в точке объявления, и ни один из двух предыдущих трюков не может быть использован для этого.
Тот, который может работать, но для которого я не знаю, будет ли он, использует decltype.