C ++ 11 lambda作为成员变量?

时间:2011-07-06 19:37:14

标签: c++ c++11 lambda

可以将lambda定义为类成员吗?

例如,是否可以使用lambda而不是函数对象重写下面的代码示例?

struct Foo {
    std::function<void()> bar;
};

我想知道的原因是因为以下lambda可以作为参数传递:

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; });
}

我认为如果lambda可以作为函数参数传递,那么也许它们也可以存储为成员变量。

经过多次修修补补后,我发现这有效(但这有点无意义):

auto say_hello = [](){ std::cout << "Hello"; };
struct Foo {
    typedef decltype(say_hello) Bar;
    Bar bar;
    Foo() : bar(say_hello) {}
};

5 个答案:

答案 0 :(得分:37)

lambda只是一个函数对象,所以,是的,你可以使用lambda初始化一个函数成员。这是一个例子:

#include <functional>
#include <cmath>

struct Example {

  Example() {
    lambda = [](double x) { return int(std::round(x)); };
  };

  std::function<int(double)> lambda;

};

答案 1 :(得分:17)

模板可以在没有类型擦除的情况下实现,但就是这样:

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也是不确定的,因为lambda表达式的每个实例都是具有唯一类型的单独闭包对象的表示法。 (例如,上面f的类型 foo<decltype([] { return 42; })>。)

答案 2 :(得分:12)

有点晚了,但我没有在这里找到这个答案。如果lambda没有捕获参数,那么它可以隐式地转换为指向具有相同参数和返回类型的函数的指针。

例如,以下程序编译正常并按预期执行:

struct a {
    int (*func)(int, int);
};

int main()
{
    a var;
    var.func = [](int a, int b) { return a+b; };
}

当然,lambdas的一个主要优点是capture子句,一旦你添加了它,那么这个技巧就行不通了。使用std :: function或模板,如上所述。

答案 3 :(得分:9)

#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 :(得分:3)

“如果lambda可以作为函数参数传递,那么也可以作为成员变量”

第一个是肯定的,您可以使用模板参数推导或“自动”来执行此操作。第二个可能是没有,因为你需要知道声明点的类型,前两个技巧都不能用于此。

可能有效的,但我不知道是否会使用decltype。