在 Visual C++ 中实现模板函数以将 lambda 表达式转换为具有不同调用约定的函数指针

问题描述 投票:0回答:1

我想创建一个模板函数,将 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++ 中可能吗?

c++ visual-c++ msvcrt
1个回答
0
投票

您不需要显式转换来将(非捕获)lambda 转换为函数指针。 当您将 lambda 分配给指针时,编译器可以隐式为您执行该转换。让它为您找出调用约定。

如果确实需要显式转换,则可以简单地使用本机

+
运算符,例如:

int (__fastcall *pFunc)(int, int) = +[](int a, int b) -> int { ... };
WriteRelCall(0x4909BC, +[](BSAnimGroupSequence* anim) -> UInt32 { ... });
© www.soinside.com 2019 - 2024. All rights reserved.