我想创建一个模板函数,将 lambda 转换为不同调用约定的函数指针。我已经尝试过这个,但它无法编译,因为模板无法推断为函数指针。
template<typename RetType, typename... Args>
auto fastcall_cast(RetType(__fastcall *func)(Args...)) -> RetType(__fastcall *)(Args...)
{
return static_cast<RetType(__fastcall *)(Args...)>(func);
}
int main() {
auto pFunc = fastcall_cast([](int a, int b) -> int {
return a + b;
});
auto result = pFunc(1, 2);
return result;
};
// <source>(8): error C2672: 'fastcall_cast': no matching overloaded function found
// <source>(2): note: could be 'RetType (__fastcall *fastcall_cast(RetType (__fastcall *)(Args...)))(Args...)'
// <source>(8): note: 'RetType (__fastcall *fastcall_cast(RetType (__fastcall *)(Args...)))(Args...)': could not deduce template argument for 'RetType (__fastcall *)(Args...)'
我以前一直依赖这个宏,但我发现它很丑陋,因为它最后需要一个额外的右括号:
#define INLINE_HOOK(retnType, callingConv, ...) static_cast<retnType(callingConv*)(__VA_ARGS__)>([](__VA_ARGS__) [[msvc::forceinline]] -> retnType
WriteRelCall(0x4909BC, INLINE_HOOK(UInt32, __fastcall, BSAnimGroupSequence* anim)
{
if (anim->textKeys->FindFirstByName("allowClampInLocomotion"))
return NiControllerSequence::kCycle_Loop;
return anim->cycleType;
}));
不可能直接在 VC++ 中的 lambda 内部指定调用约定,因为它会简单地忽略它并显示警告指出
warning C4229: anachronism used: modifiers on data are ignored
。显然你需要投射它。
理想情况下,模板函数不需要任何显式模板参数,并且可以从 lambda 本身推导出来。
这在 Visual C++ 中可能吗?
您不需要显式转换来将(非捕获)lambda 转换为函数指针。 当您将 lambda 分配给指针时,编译器可以隐式为您执行该转换。让它为您找出调用约定。
如果确实需要显式转换,则可以简单地使用本机
+
运算符,例如:
int (__fastcall *pFunc)(int, int) = +[](int a, int b) -> int { ... };
WriteRelCall(0x4909BC, +[](BSAnimGroupSequence* anim) -> UInt32 { ... });