Подтвердить что ты не робот

С++ 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) {}
};
4b9b3361

Ответ 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.