使用推导this调用最派生方法时的编译错误及疑问
关于C++“推导this”模式与运行时多态类型不一致的疑问
示例代码
#include <print> struct base { template <typename Self> void invoke(this Self& self) { self.foo(); } }; struct derived : base { void foo() { std::println("derived::foo()"); } }; int main() { derived d; d.invoke(); // ok base& bref = d; bref.invoke(); // error base* bptr = &d; bptr->invoke(); // error return 0; }
编译器错误信息
<source>:8:12: error: no member named 'foo' in 'base' 8 | self.foo(); | ~~~~ ^ <source>:23:6: note: in instantiation of function template specialization 'base::invoke<base>' requested here 23 | bref.invoke(); // error | ^
疑问
使用“推导this”时所用的基类类型,为何与常规运行时多态中的预期类型不一致?
解析
这是因为推导this本质是编译期的模板参数推导,和运行时多态的动态绑定完全是两套机制:
- 当通过
derived对象调用invoke时,模板参数Self被推导为derived,self.foo()直接调用derived::foo(),因此正常运行。 - 当通过
base&或base*调用invoke时,模板推导只会看调用点的静态类型(也就是base),所以Self被推导为base。而base类中并没有定义foo方法,自然会触发编译错误——这个过程完全和运行时实际指向的derived对象无关。 - 常规运行时多态依赖虚函数机制,是运行时行为:它会根据对象的实际类型(而非静态类型),通过虚函数表找到对应的函数调用。你的代码里
foo不是虚函数,即便用推导this也无法实现这种动态匹配。
如果要在推导this模式下实现类似多态的效果,可以给基类添加虚函数:
struct base { virtual void foo() = 0; // 纯虚函数,强制派生类实现 template <typename Self> void invoke(this Self& self) { self.foo(); // 此时会触发动态绑定,调用实际类型的foo } };
内容的提问来源于stack exchange,提问作者Penny Dreudter
相关产品推荐
相关产品推荐

