将捕获 lambda 作为函数指针传递 [英] Passing capturing lambda as function pointer

查看:65
本文介绍了将捕获 lambda 作为函数指针传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以将 lambda 函数作为函数指针传递?如果是这样,我一定是做错了什么,因为我收到了编译错误.

Is it possible to pass a lambda function as a function pointer? If so, I must be doing something incorrectly because I am getting a compile error.

看下面的例子

using DecisionFn = bool(*)();

class Decide
{
public:
    Decide(DecisionFn dec) : _dec{dec} {}
private:
    DecisionFn _dec;
};

int main()
{
    int x = 5;
    Decide greaterThanThree{ [x](){ return x > 3; } };
    return 0;
}

当我尝试编译此时,出现以下编译错误:

When I try to compile this, I get the following compilation error:

In function 'int main()':
17:31: error: the value of 'x' is not usable in a constant expression
16:9:  note: 'int x' is not const
17:53: error: no matching function for call to 'Decide::Decide(<brace-enclosed initializer list>)'
17:53: note: candidates are:
9:5:   note: Decide::Decide(DecisionFn)
9:5:   note: no known conversion for argument 1 from 'main()::<lambda()>' to 'DecisionFn {aka bool (*)()}'
6:7:   note: constexpr Decide::Decide(const Decide&)
6:7:   note: no known conversion for argument 1 from 'main()::<lambda()>' to 'const Decide&'
6:7:   note: constexpr Decide::Decide(Decide&&)
6:7:   note: no known conversion for argument 1 from 'main()::<lambda()>' to 'Decide&&'

这是一个需要消化的错误消息,但我认为我从中得到的是不能将 lambda 视为 constexpr,因此我无法将其作为函数传递指针?我也尝试将 x 设为 const,但这似乎没有帮助.

That's one heck of an error message to digest, but I think what I'm getting out of it is that the lambda cannot be treated as a constexpr so therefore I cannot pass it as a function pointer? I've tried making x const as well, but that doesn't seem to help.

推荐答案

一个 lambda 只能转换为函数指针,如果它没有捕获,来自 草案 C++11 标准部分 5.1.2 [expr.prim.lambda] 说(强调我的):

A lambda can only be converted to a function pointer if it does not capture, from the draft C++11 standard section 5.1.2 [expr.prim.lambda] says (emphasis mine):

一个 lambda 表达式的闭包类型没有 lambda-capture 有一个公共非虚拟非显式 const 函数到指针的转换具有与闭包相同的参数和返回类型的函数类型的函数调用运算符.此转换返回的值function 应该是一个函数的地址,该函数在调用时具有与调用闭包类型的函数调用运算符的效果相同.

The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.

请注意,cppreference 在他们关于 Lambda 函数的部分中也涵盖了这一点.

Note, cppreference also covers this in their section on Lambda functions.

因此以下替代方案可行:

So the following alternatives would work:

typedef bool(*DecisionFn)(int);

Decide greaterThanThree{ []( int x ){ return x > 3; } };

这也是:

typedef bool(*DecisionFn)();

Decide greaterThanThree{ [](){ return true ; } };

并且正如 5gon12eder 指出的那样,您也可以使用 std::function,但请注意 std::function 很重,所以它不是一个没有成本的权衡.

and as 5gon12eder points out, you can also use std::function, but note that std::function is heavy weight, so it is not a cost-less trade-off.

这篇关于将捕获 lambda 作为函数指针传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆