CRTP来避免dynamic多态性

如何在C ++中使用CRTP来避免虚拟成员函数的开销?

有两种方法。

第一个是通过静态指定types结构的接口:

template <class Derived> struct base { void foo() { static_cast<Derived *>(this)->foo(); }; }; struct my_type : base<my_type> { void foo(); // required to compile. }; struct your_type : base<your_type> { void foo(); // required to compile. }; 

第二个是避免使用reference-to-base或pointer-to-base习语,并在编译时进行连线。 使用上面的定义,你可以使用如下的模板函数:

 template <class T> // T is deduced at compile-time void bar(base<T> & obj) { obj.foo(); // will do static dispatch } struct not_derived_from_base { }; // notice, not derived from base // ... my_type my_instance; your_type your_instance; not_derived_from_base invalid_instance; bar(my_instance); // will call my_instance.foo() bar(your_instance); // will call your_instance.foo() bar(invalid_instance); // compile error, cannot deduce correct overload 

所以在你的函数中结合结构/接口定义和编译时types的推导,你可以做静态调度而不是dynamic调度。 这是静态多态的本质。

我一直在寻找CRTP的体面讨论。 Todd Veldhuizen的科学C ++技术是这个(1.3)和许多其他高级技术(如expression式模板)的很好的资源。

另外,我发现你可以在Google书籍上阅读Coplien最初的C ++ Gems文章。 也许情况仍然如此。

我必须查找CRTP 。 但是,做了这些之后,我发现了一些关于Static Polymorphism的东西。 我怀疑这是你的问题的答案。

事实certificate, ATL相当广泛地使用这种模式。

这维基百科答案有你需要的一切。 即:

 template <class Derived> struct Base { void interface() { // ... static_cast<Derived*>(this)->implementation(); // ... } static void static_func() { // ... Derived::static_sub_func(); // ... } }; struct Derived : Base<Derived> { void implementation(); static void static_sub_func(); }; 

虽然我不知道这实际上买了多less钱。 虚函数调用的开销是(当然是依赖于编译器):

  • 内存:每个虚函数一个函数指针
  • 运行时:一个函数指针调用

虽然CRTP静态多态性的开销是:

  • 内存:每个模板实例的基础重复
  • 运行时:一个函数指针调用+无论static_cast正在做什么