将lambda函数强制转换为函数指针是否安全? [英] Is it safe to cast a lambda function to a function pointer?

查看:106
本文介绍了将lambda函数强制转换为函数指针是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码:

void foo(void (*bar)()) {
    bar();
}

int main() {
    foo([] {
        int x = 2;
    });
}

但是,我担心这将遭受与以下相同的命运:

However, I'm worried that this will suffer the same fate as:

struct X { int i; };

void foo(X* x) {
    x->i = 2;
}

int main() {
    foo(&X());
}

其中一个是局部变量的地址。

Which takes the address of a local variable.

第一个示例是否完全安全?

Is the first example completely safe?

推荐答案

是的,我相信第一个示例都是安全的,无论评估涉及较少捕获的lambda表达式的完整表达式期间创建的所有临时对象的生命周期。

Yes I believe the first example is safe, regardless of the life-time of all the temporaries created during the evaluation of the full-expression that involves the capture-less lambda-expression.

每个工作草案(n3485) 5.1.2 [expr.prim.lambda] p6

Per the working draft (n3485) 5.1.2 [expr.prim.lambda] p6


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

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.

上面的段没有提到在评估了lambda表达式后指向函数的指针的有效性。

The above paragraph says nothing about the pointer-to-function's validity expiring after evaluation of the lambda-expression.

例如,我希望以下代码能起作用:

For e.g., I would expect the following to work:

auto L = []() {
   return [](int x, int y) { return x + y; };
};

int foo( int (*sum)(int, int) ) { return sum(3, 4); }


int main() {
  foo( L() );
}

虽然clang的实现细节当然不是C ++的最终用语(标准是),如果可以让您感觉更好,则在clang中实现的方式是,当对lambda表达式进行解析并进行语义分析时,会为lambda表达式创建一个闭包类型,并向类添加静态函数,语义类似于lambda的函数调用运算符。因此,即使由 L()返回的lambda对象的生命周期超过了 foo的主体之内,向指针到函数的转换也会返回仍然有效的静态函数的地址。

While implementation details of clang are certainly not the final word on C++ (the standard is), if it makes you feel any better, the way this is implemented in clang is that when the lambda expression is parsed and semantically analyzed a closure-type for the lambda expression is invented, and a static function is added to the class with semantics similar to the function call operator of the lambda. So even though the life-time of the lambda object returned by 'L()' is over within the body of 'foo', the conversion to pointer-to-function returns the address of a static function that is still valid.

考虑一些类似的情况:

struct B {
   static int f(int, int) { return 0; }
   typedef int (*fp_t)(int, int);
   operator fp_t() const { return &f; }
};
int main() {
  int (*fp)(int, int) = B{};
  fp(3, 4); // You would expect this to be ok.
}

我当然不是核心c ++专家,但是FWIW,这是我的解释标准的字母,我认为它是可以辩护的。

I am certainly not a core-c++ expert, but FWIW, this is my interpretation of the letter of the standard, and I feel it is defendable.

希望这会有所帮助。

这篇关于将lambda函数强制转换为函数指针是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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