输入关键词开始搜索

CRTP — 静态多态与编译期继承

基本形式

template <typename Derived>
class Base {
public:
    void interface() {
        static_cast<Derived *>(this)->impl();  // 编译期绑定
    }
};

class MyClass : public Base<MyClass> {
public:
    void impl() { std::cout << "MyClass\n"; }
};

MyClass obj;
obj.interface();  // 无虚函数调用,编译期确定地址

核心:基类把自己”向下转型”为派生类,在编译期直接调用派生类方法。零运行时开销。

vs 虚函数的性能差异

// 虚函数:运行时查 vtable
class Animal {
public: virtual void speak() = 0;
};
void call(Animal &a) { a.speak(); }  // 间接调用

// CRTP:编译期绑定 → 可内联
template <typename T>
void call(Base<T> &b) { b.interface(); }  // 编译期确定调用地址

// 基准测试(100 万次调用)
// 虚函数: ~5ms(一次间接跳转)
// CRTP:   ~0.5ms(编译器内联后可能直接消除函数调用)

混入 (Mixin) — 组合功能

// 给任意类加 operator==
template <typename Derived>
class Comparable {
    friend bool operator==(const Derived &a, const Derived &b) {
        return a.tie() == b.tie();  // 依赖派生类的 tie()
    }
};

class Point : public Comparable<Point> {
    int x, y;
public:
    Point(int x, int y) : x(x), y(y) {}
    auto tie() const { return std::tie(x, y); }
};

Point p1(1, 2), p2(1, 2);
p1 == p2;  // ✅ true — Comparable 自动生成

常见应用

// ① enable_shared_from_this 就是 CRTP
class MyClass : public std::enable_shared_from_this<MyClass> {};

// ② std::ranges::view_interface 也是 CRTP
template <typename Derived>
class view_interface { /* 提供 front/back/empty/operator[] */ };

// ③ 计数器混入
template <typename Derived>
class Counter {
    static inline int count = 0;
public:
    Counter() { ++count; }
    ~Counter() { --count; }
    static int instances() { return count; }
};
class MyWidget : public Counter<MyWidget> {};

编译期多态选择

虚函数CRTPConcepts
运行时多态
编译期内联
基类指针统一存储
可读性
二进制体积+vtable模板膨胀模板膨胀

决策:需要运行时存 vector<Base *> → 虚函数。不需要运行时多态但想复用代码 → CRTP 或 Concepts。