如何仅根据函数指针推断模板类型参数并复用该推断类型?
解决方法
你的问题根源在于模板参数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
相关产品推荐
相关产品推荐

