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

如何仅根据函数指针推断模板类型参数并复用该推断类型?

解决方法

你的问题根源在于模板参数Args会同时从函数指针fp和后续的args参数进行推导,当两者类型不完全匹配时(比如子类指针转基类指针、int转double),编译器会因为推导结果冲突报错。要让Args仅从fp推导,只需把args的参数类型设置为非推导上下文,阻止编译器从args推导模板参数。

C++20及以上版本实现

直接用标准库的std::type_identity_t修改模板:

#include <type_traits>

template<typename R, typename... Args>
void f(R(*fp)(Args...), std::type_identity_t<Args>... args) {
    fp(args...);
}

测试示例:

#include <iostream>
struct Base {};
struct Derived : Base {};

void func_base(Base*) { std::cout << "Base* called\n"; }
void func_double(double d) { std::cout << "Double: " << d << "\n"; }

int main() {
    Derived d;
    f(func_base, &d); // Derived* 自动转 Base*,正常编译
    
    f(func_double, 0); // int 0 自动转 double,正常编译输出 Double: 0
}

C++17及更早版本实现

如果用不了C++20,自己实现一个type_identity工具:

template<typename T>
struct type_identity {
    using type = T;
};

template<typename T>
using type_identity_t = typename type_identity<T>::type;

// 然后用这个自定义的type_identity_t修改模板
template<typename R, typename... Args>
void f(R(*fp)(Args...), type_identity_t<Args>... args) {
    fp(args...);
}

成员函数指针的适配

如果要支持成员函数指针,逻辑完全一致,只需调整模板参数:

#include <type_traits>

template<typename R, typename C, typename... Args>
void f(R(C::*fp)(Args...), C& obj, std::type_identity_t<Args>... args) {
    (obj.*fp)(args...);
}

原理很简单:type_identity_t<T>会让编译器忽略该参数的类型推导,只使用从fp推导出来的Args类型,然后自动将传入的args隐式转换为Args对应的类型,完美解决类型不匹配的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 10:53:34