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

使用成员函数指针跨类调用方法时的模板匹配问题

解决成员函数指针与函数模板的匹配问题

问题根源

  • apply1调用失败原因:调用b.apply1(&Eggs::f1, s)时,模板参数T会从两个位置推导:
    1. 从成员函数指针void (Eggs::*)(const Spam&)推导出T = const Spam&
    2. 从第二个参数s(类型Spam)推导出T = Spam
      两个推导结果矛盾,编译器无法确定T的类型,导致模板实例化失败。
  • apply2调用失败原因:第二个参数是my_type_identity<T>类型,但你传递的是Spam对象,类型不匹配;同时T的推导依然存在冲突——成员函数指针推导出T = const Spam&,但my_type_identity<T>没法匹配Spam,最终推导失败。

解决方案

核心思路是让模板参数T只从成员函数指针推导,把第二个参数的类型设置为非推导上下文,避免推导冲突。用你定义的my_type_identity就能实现这个效果:

修正后的代码

template<class T> struct my_type_identity { using type = T; };

struct Spam {};

struct Eggs {
    void f0(Spam)         {}
    void f1(const Spam&) {}
};

template <class C> struct Bread {
    C c;
    // 关键修正:第二个参数用非推导上下文,T仅从成员函数指针推导
    template <class F, class T>
    void apply(void (F::*f)(T), typename my_type_identity<T>::type t) {
        (c.*f)(t);
    }
};

int main() {
    Spam s;
    Bread<Eggs> b;
    b.apply(&Eggs::f0, s); // 正常运行
    b.apply(&Eggs::f1, s); // 正常运行:s会自动转成const Spam&
}

关键说明

  • typename my_type_identity<T>::type属于非推导上下文,编译器不会从第二个参数推导T,只会根据成员函数指针确定T的类型。
  • 对于f1,T会被推导为const Spam&,第二个参数的类型就是const Spam&,传递Spam对象s时会自动隐式转换,完全符合函数调用要求。
  • 如果用C++20及以上版本,直接用标准库的std::type_identity替代自定义的my_type_identity就行,效果一样。

内容的提问来源于stack exchange,提问作者Captain'Flam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:20:44