CRTP 编译时多态性的优点和用例是什么?

What are the adavantages and use cases of CRTP compiletime polymorphism?

我看到我们可以使用 CRTP 引入某种编译时多态性,但是我想知道这比旧的虚函数有什么好处。最后我们必须调用 static_cast<const T*>(this)->implementation(); ,这是一个间接级别,就像 vtable 所做的那样。 它们有何不同?有什么优势吗?我只看到它们不能被基类破坏的缺点。对我来说,它作为学术考试看起来不错,但以常规多态性为主。

原因是性能。

static_cast<const T*>(this)->implementation(); 在编译时解析为相应 T::implementation() 重载的地址:

    CALL <fixed-address>

另一方面,虚拟成员调用通常在 运行 时通过 vtable 中的偏移量使用间接调用来解析。在最简单的情况下,优化器可以将其转换为编译时,但没有办法可靠地做到这一点。所以通常你可以期望代码看起来像这样:

    MOV rax, <vtable-ptr>
    MOV rax, [rax+<offset>] ; Indirection via a vtable
    CALL rax

由于对目标地址的数据依赖,这种类型的调用很可能会在第一次调用时出现管道停顿,而后续调用将在很大程度上依赖于分支预测器的质量。

另一方面,静态调用非常快,因为它不涉及管道停顿。