将非空返回类型的Lambda转换为函数指针

Zheng Qu

我正在尝试将lambda函数转换为函数指针但是,当lambda具有非空返回类型时,强制转换失败。详细信息请参见代码段。

是否可以fun2转换为通用函数指针,我可以将其保存以备后用?

更新:我的意图是将各种函数转换为“通用函数指针”,该指针可以保存在中std::map使用后,我将其转换回其原始函数类型。

#include <iostream>

int fun3() { return 1; }

int main(int argc, char *argv[]) {

  typedef void (*voidFunctionType)(void);

  // Case 1: lambda, return type void 
  auto fun1 = []() { std::cout << "hello" << std::endl; };
  // -> compiles
  auto casted_fun1 = (voidFunctionType)fun1;

  // Case 2: lambda, return type int
  auto fun2 = []() { std::cout << "world" << std::endl; return -1;};
  // -> error: invalid cast from type ‘main(int, char**)::<lambda()>’ to type ‘voidFunctionType {aka void (*)()}’
  auto casted_fun2 = (voidFunctionType)fun2;

  // Case 3: free function, return type int -> compiles
  auto casted_fun3 = (voidFunctionType)fun3;

  return 0;
}
核桃

问题是您正在使用C风格的显式强制转换。这些都是非常危险的。

在这种情况下,这里的问题是fun3(与相对fun2)已经衰减为类型的函数指针int(*)()

然后,将其投射到void(*)()之所以可行,是因为C样式强制转换将尝试执行不同的C ++强制转换表达式,直到一个有效为止。特别是它还会尝试一个reinterpret_cast

reinterpret_cast<voidFunctionType>(fun3)

之所以有效,是因为reinterpret_cast可以将任何函数指针转换为任何其他函数指针。

但是,不允许您通过获取的指针来调用该函数。这样做会使您的程序具有未定义的行为如您所见,此演员表的用途非常有限,如果您不了解它,将会很危险。

不要使用C样式强制转换,static_cast<voidFunctionType>(fun3)而应使用C样式强制转换,这两种情况下您都会得到适当的编译时错误。

您不能使用返回一种类型的函数(无论是自由函数还是lambda),就好像它返回了另一种(或没有)类型一样。因此,将返回的lambda强制int转换void(*)()是没有意义的。


如果确实要保存任意函数指针,则可以通过首先将lambda转换为函数指针,然后使用来将其转换为目标函数指针类型,从而使lambda转换起作用reinterpret_cast我仍然不会使用C样式强制转换,因为这reinterpret_cast至少会清楚表明您打算进行哪种强制转换

auto casted_fun2 = reinterpret_cast<voidFunctionType>(+fun2);

一元+是强制lambda进行函数指针转换的常见技巧。但是也请注意,只有没有捕获的lambda才能转换为函数指针。

如前所述,您必须在调用指针之前将其强制转换回其原始类型,因此您需要将类型信息存储在某处。我不确定您打算怎么做,但是您可能需要实现的扩展版本std::function,例如,请参见此问题的实现方式std::function

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章