我正在尝试将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
可以将any函数指针转换为any其他函数指针。
但是,不允许您通过获取的指针来调用该函数。这样做会使您的程序具有undefined behavior。如您所见,此演员表的用途非常有限,如果您不了解它,将会很危险。
不要使用C样式强制转换,而应使用static_cast<voidFunctionType>(fun3)
,在两种情况下,您都将获得适当的编译时错误。
您不能使用返回一种类型的函数(无论是自由函数还是lambda),就好像它返回了另一种(或没有)类型一样。因此,将返回int
的lambda转换为void(*)()
没有任何意义。
如果您确实要保存任意函数指针,则可以通过首先将其转换为函数指针,然后使用reinterpret_cast
将其强制转换为目标函数指针类型来使lambda转换起作用。我仍然不会使用C样式转换,因为reinterpret_cast
至少会清楚表明您打算进行哪种转换:
auto casted_fun2 = reinterpret_cast<voidFunctionType>(+fun2);
一元+
是强制lambda进行函数指针转换的常见技巧。
如上所述,您必须在调用指针之前将其强制转换回其原始类型,因此您需要将类型信息存储在某个地方。我不确定您打算怎么做,但是您可能需要实现std::function
的某些扩展版本,例如this question了解std::function
的操作方式。