CRTP to avoid dynamic polymorphism

How can I use CRTP in C ++ to avoid the overhead of virtual member actions?

+87
c ++ virtual templates crtp
Nov 04 '08 at 16:07
source share
4 answers

There are two ways.

The first one is specifying the interface statically for the type structure:

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. }; 

Secondly, avoid using a reference to a base or a pointer to a base and post at compile time. Using the definition above, you can have template functions that look like this:

 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 

Thus, combining the definition of the structure / interface and the deduction of the type of compilation time in your functions allows you to perform static dispatching instead of dynamic dispatch. This is the essence of static polymorphism.

+135
Nov 04 '08 at 19:02
source share

I was looking for decent CRTP discussions. Todd Veldhuizen Methods for Scientific C ++ is an excellent resource for this (1.3) and many other best practices, such as expression templates.

Also, I found that you can read most of the original Coplien C ++ Gems article in Google books. Maybe this is still the case.

+18
Nov 04 '08 at 17:49
source share

I had to look for CRTP . However, having done this, I found some of Static Polymorphism . I suspect this is the answer to your question.

It turns out that ATL uses this pattern quite widely.

+1
Nov 04 '08 at 16:11
source share

This Wikipedia answer has everything you need. Namely:

 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(); }; 

Although I do not know how much this actually buys you. The overhead of calling a virtual function (of course, depends on the compiler):

  • Memory: one pointer to each virtual function
  • Runtime: one function pointer call

While the overhead of static CRTP polymorphism:

  • Memory: duplication of the base for each instance of the template
  • Runtime: one call to function pointer + no matter what static_cast does
-four
Nov 04 '08 at 16:12
source share



All Articles