我正在尝试将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] 删除。
我来说两句