You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++模板结构体方法如何从函数类型声明推导返回值与参数类型

从函数类型推导返回值与参数列表的实现方案

完全可以通过C++模板偏特化机制实现你要的效果,不管是普通函数指针、带自定义调用约定的函数指针,都能自动拆解出返回类型和参数列表,不需要依赖额外的编译器扩展。

核心实现逻辑是:先声明模板主类,再针对「函数指针」这一类型模式写偏特化版本,在偏特化参数里直接把返回值类型、各位置参数类型拆成独立的模板参数,后续类内的call方法直接用拆出来的类型定义即可。

你给出的fnOurFunc_t这类自定义函数指针类型同样适用,编译器在模板实例化时会自动匹配对应的偏特化版本,提取出void*作为返回类型,const char*/int/float**作为三个参数的类型。

可直接运行的实现代码

#include <iostream>
#include <utility>

// 主模板前置声明,仅匹配函数指针类型的偏特化版本可实例化
template<class T>
struct _function_wrapper_t;

// 函数指针类型偏特化:自动拆解返回值Ret、参数包Args...
template<class Ret, class... Args>
struct _function_wrapper_t<Ret(*)(Args...)>
{
    // 构造时存入目标函数指针
    explicit _function_wrapper_t(Ret(*pfn)(Args...)) noexcept
        : m_pfnFunc(reinterpret_cast<void*>(pfn))
    {}

    // 用拆解出的类型定义call方法签名
    Ret call(Args... args)
    {
        // 转回原始函数指针类型调用,用forward完美转发避免不必要的参数拷贝
        using pfn_t = Ret(*)(Args...);
        return (reinterpret_cast<pfn_t>(m_pfnFunc))(std::forward<Args>(args)...);
    }

    void* m_pfnFunc;
};

// 测试用普通函数
int MultiplyTwoNumbers(int nNum, int nNum2)
{
    return nNum * nNum2;
}

int MultiplyThreeNumbers(int nNum, int nNum2, int* pnNum3)
{
    return nNum * nNum2 * *pnNum3;
}

// 你举例的自定义调用约定函数指针类型
typedef void*(__cdecl* fnOurFunc_t)(const char*, int, float**);

int main()
{
    _function_wrapper_t<decltype(&MultiplyTwoNumbers)> two(&MultiplyTwoNumbers);
    _function_wrapper_t<decltype(&MultiplyThreeNumbers)> three(&MultiplyThreeNumbers);

    auto ret1 = two.call(1, 2);
    int num3 = 8;
    auto ret2 = three.call(4, 5, &num3);
    std::cout << ret1 << " " << ret2 << std::endl; // 输出2 160

    // 自定义函数指针类型测试
    void* testCustomFunc(const char* str, int val, float** ppFloat) {
        (void)str; (void)val; (void)ppFloat;
        return nullptr;
    }
    _function_wrapper_t<fnOurFunc_t> customWrap(testCustomFunc);
    customWrap.call("demo", 1024, nullptr); // 编译通过,签名完全匹配
}

扩展说明

  • 如果需要兼容其他调用约定(比如Windows平台常用的__stdcall、__fastcall),或者类成员函数指针,只需要新增对应模式的偏特化版本即可,类型拆解逻辑和上面的普通函数指针版本完全一致。
  • 以上实现基于C11及以上标准的可变参数模板特性,可以自动适配任意个数的函数参数;如果需要兼容C03老标准,只需要按照业务需要支持的最大参数个数,手写对应参数数量的偏特化重载即可。
  • 存储函数指针用void*是可行的,但调用时必须准确转回和原函数完全一致的指针类型,转错类型会触发未定义行为。

内容的提问来源于stack exchange,提问作者Zachary Washburn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 19:57:21