1. 什么是 CRTP
Curiously Recurring Template Pattern。子类作为父类模板参数,父类用 static_cast<T*>(this) 调用子类方法,实现编译期多态。
2. 代码示例
#include <iostream>// 父类:模板参数 T 必须是继承它的子类
template <typename T>
struct Base {// 通过 static_cast 将 this 转换为子类指针,再调用子类的 hello()void hello() {static_cast<T*>(this)->hello();}
};// 子类:传入自己作为父类模板参数
struct Derived : Base<Derived> {void hello() {std::cout << "Hello from Derived\n";}
};int main() {Derived d;Base<Derived>* ptr = &d; // 父类指针指向子类对象ptr->hello(); // 实际调用到 Derived::hello()
}
3. 为什么 CRTP 无 vtable 开销
vtable 只在 ptr->virtual_fn() 通过父类指针调用虚函数时才会触发。CRTP 中调用 hello() 的是子类指针,不是父类。
4. MLIR 中的 CRTP
// mlir/IR/OpDefinition.h
template <typename ConcreteType, typename... Traits>
class Op : public Op<ConcreteType>::template Impl<Traits...> {Operation* getOperation() {// static_cast 实现静态多态,无虚表查找return static_cast<ConcreteType*>(this)->getOperation();}
};
TableGen 生成的 trait 接口代码大量使用此模式,所有 trait 方法在编译时绑定,实现零运行时开销的验证逻辑。
