views:

2031

answers:

7

What are some practical uses for the "Curiously Recurring Template Pattern"? The "counted class" example commonly shown just isn't a convincing example to me.

+11  A: 

Simulated dynamic binding. Avoiding the cost of virtual function calls while retaining some of the hierarchical benefits is an enormous win for the subsystems where it can be done in the project I am currently working on.

moonshadow
What kind of percentage performance and/or memory useage gains do you get, btw?
Steve Jessop
I've seen time spent in a calculation decrease by an order of magnitude. This was, admittedly, a very unusal corner case, it is usually much less dramatic. The memory usage gains are a negligible proportion of overall memory usage for us.
moonshadow
I can't see how it can be used. Polymorhpishm works by using a base class pointer to call derived class methods according to the type of the derived class. However in the CRTP code you still have totemplate< typename derived >class base{public: void impl(){ static_cast<derived*>( this )->impl(); }};class derived : public base< derived > { void impl() { /* something */ }};base< derived *> basePtr;So you've still had to mention the derived class in the template which kind of defeats the polymorphic aspect as I've had to explicitly state the derived class
ScaryAardvark
+1  A: 

Generally it is used for polymorphic-like patterns where you do not need to be able to choose the derived class at runtime, only at compile time. This can save the overhead of the virtual function call at runtime.

Greg Rogers
@Greg: can you give a code example? before: [[class B{virtual void f()=0;void g(){ .. f(); .. } };class D:B{void f();};]] after [[template<class Der>class B{void g(){static_cast<Der*>(this)->f();}};class D:B<D>{void f();};]] etc, but elaborate, perhaps with more relatable example types.
Aaron
A: 

It feels sort of like C macro: take advantage that the macro is compiled not at the time of definition, but at the time of usage.

#define CALL_THE_RIGHT_FOO foo()

file A:

static void foo() {
   // do file A thing
}
...
CALL_THE_RIGHT_FOO
...

file A:

static void foo() {
   // do file B thing
}
...
CALL_THE_RIGHT_FOO
...

The template usage pattern you're describing allows us do "call the right foo" in the parent template, postponing the definition of what exactly the right foo is till the template is instantiated. Except in this case it's the distinction between ClassA::foo and ClassB::foo based on the value of T in Parent.

Arkadiy
+8  A: 

It's also especially useful for mixins (by which I mean classes you inherit from to provide functionality) which themselves need to know what type they are operating on (and hence need to be templates).

In Effective C++, Scott Meyers provides as an example a class template NewHandlerSupport<T>. This contains a static method to override the new handler for a particular class (in the same way that std::set_new_handler does for the default operator new), and an operator new which uses the handler. In order to provide a per-type handler, the parent class needs to know what type it is acting on, so it needs to be a class template. The template parameter is the child class.

You couldn't really do this without CRTP, since you need the NewHandlerSupport template to be instantiated separately, with a separate static data member to store the current new_handler, per class that uses it.

Obviously the whole example is extremely non-thread-safe, but it illustrates the point.

Meyers suggests that CRTP might be thought of as "Do It For Me". I'd say this is generally the case for any mixin, and CRTP applies in the case where you need a mixin template rather than just a mixin class.

Steve Jessop
A: 

The CRTP gets a lot less curious if you consider that the subclass type that is passed to the superclass is only needed at time of method expansion. So then all types are defined. You just need the pattern to import the symbolic subclass type into the superclass, but it is just a forward declaration - as all formal template param types are by definition - as far as the superclass is concerned.

We use in a somewhat modified form, passing the subclass in a traits type structure to the superclass to make it possible for the superclass to return objects of the derived type. The application is a library for geometric calculus ( points, vectors, lines, boxes ) where all the generic functionality is implemented in the superclass, and the subclass just defines a specific type : CFltPoint inherits from TGenPoint. Also CFltPoint existed before TGenPoint, so subclassing was a natural way of refactoring this.

QBziZ
@QBizZ: Are you aware that this might be implemented through virtual functions as well? A virtual function returning a pointer to a base class might return a pointer to a derived class inside the derived class
the_drow
A: 

For a real-world library use of CRTP, look at ATL and WTL (wtl.sf.net). It is used extensively there for compile-time polymorphism.

Roel
A: 

I thought that the point of the CRTP was to break the dependency on the implementation (access via interface) and provide replaceable implementation ? I don't understand how you would do this if all the accessors (the objects calling the interface) need to know both the Interface type and the templated Implementation ?

wodger