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) {}
};
61706 次浏览
#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();
}

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

#include <functional>
#include <cmath>


struct Example {


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


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


};

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

第一个是肯定的,你可以使用模板参数演绎或“自动”这样做。第二种可能是否定的,因为您需要在声明点知道类型,而前两种技巧都不能用于此目的。

一个可能有效但我不知道是否有效的方法是使用 dectype。

模板使得没有类型擦除成为可能,但仅此而已:

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

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

例如,下面的程序可以很好地进行编译,并且能够完成您所期望的工作:

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


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

当然,lambdas 的主要优点之一是捕获子句,一旦您添加了这个子句,那么这个技巧就不起作用了。使用 std: : 函数或模板,如上所述。

只要 lambda 是常量(不包括闭包) ,就可以这样做:

#include <iostream>


template<auto function>
struct Foo
{
decltype(function) bar = function;
};


void call_lambda(auto&& lambda)
{
lambda();
}


int main()
{
Foo<[](){ std::cout << "Hello"; }> foo;
foo.bar();
call_lambda(foo.bar);
}

Https://godbolt.org/z/w5k1rexv3

或者我们可以应用演绎指南,让它适用于所有的 lambda:

#include <iostream>


template<typename T>
struct Foo
{
T bar;
};


template<typename T>
Foo(T) -> Foo<std::decay_t<T>>;


void call_lambda(auto&& lambda)
{
lambda();
}


int main()
{
std::string hello = "Hello";
Foo foo([&](){ std::cout << hello; });
foo.bar();
call_lambda(foo.bar);
}

Https://godbolt.org/z/cenrztbz4