How do I pass template parameters to a CRTP?

c++, crtp, templates

Solution

The CRTP pattern is typically used to enable static polymorphism and the ability to mixin (parametrized) behavior. To illustrate two alternatives, it's convenient to first define a general template

template
<
        typename Derived
>
class enable_down_cast
{
private:
        // typedefs

        typedef enable_down_cast Base;

public:
        Derived const* self() const
        {
                // casting "down" the inheritance hierarchy
                return static_cast<Derived const*>(this);
        }

        // write the non-const version in terms of the const version
        // Effective C++ 3rd ed., Item 3 (p. 24-25)
        Derived* self()
        {
                return const_cast<Derived*>(static_cast<Base const*>(this)->self());
        }

protected:
        // disable deletion of Derived* through Base*
        // enable deletion of Base* through Derived*
        ~enable_down_cast() = default; // C++11 only, use ~enable_down_cast() {} in C++98
};

Then you define an interface class template for the type of behavior that you want

template<typename FX>
class FooInterface
:
    // enable static polymorphism
    public enable_down_cast< FX >
{
private:
    // dependent name now in scope
    using enable_down_cast< FX >::self;

public:
    // interface
    void foo() { self()->do_foo(); }

protected:
    // disable deletion of Derived* through Base*
    // enable deletion of Base* through Derived*
    ~IFooInterface() = default; // C++11 only, use ~IFooInterface() {} in C++98/03
};

To get different implementations of this interface, simply define different classes that each derive from `FooInterface` with themselves as curiously recurring template parameters:

class FooImpl
:
    public FooInterface< FooImpl > 
{
private:
    // implementation
    friend class FooInterface< FooImpl > ;
    void do_foo() { std::cout << "Foo\n"; }
};

class AnotherFooImpl
:
    public FooInterface< AnotherFooImpl > 
{
private:
    // implementation
    friend class FooInterface< AnotherFooImpl >;
    void do_foo() { std::cout << "AnotherFoo\n"; }
};

The alternative is to parametrize the different implementations of an interface. This time, the class template depends on both a template-template parameter and a non-type parameter

template<template<int> class F, int X>
class BarInterface
:
    public enable_down_cast< F<X> >
{
private:
    // dependent name now in scope
    using enable_down_cast< F<X> >::self;

public:
    // interface
    void bar() { self()->do_bar(); }    

protected:
    // disable deletion of Derived* through Base*
    // enable deletion of Base* through Derived*
    ~BarInterface() = default; // C++11 only, use ~BarInterface() {} in C++98/03
};

The implementation is then another class template, which derives from the interface with both itself and the non-type parameter as arguments

template< int X >
class BarImpl
:
    public BarInterface< BarImpl, X > 
{
private:
    // implementation
    friend class BarInterface< ::BarImpl, X >;
    void do_bar() { std::cout << X << "\n"; }    
};

This is how you call them:

int main()
{
    FooImpl f1;         
    AnotherFooImpl f2;
    BarImpl< 1 > b1;
    BarImpl< 2 > b2;

    f1.foo();
    f2.foo();
    b1.bar();
    b2.bar();

    return 0;
}

The classes in your question don't quite fit into this general pattern. If you might want to give `Derived` some CRTP-like behavior, then you can either do

class Derived1
: 
   public CRTP< Derived1 > 
{

};

template<int I>
class Derived2
: 
   public CRTPInt< Derived2, I >
{

};

UPDATE: Based on the discussion from https://stackoverflow.com/a/11571808/819272, I discovered that the original answer only compiled on Visual Studio 2010, but not on gcc because of some Microsoft-specific, non-portable features. E.g. the `self()` function from `enable_down_cast` is a (template) dependent name in its derived classes, and therefore not visible without explicit `using` directives. Furthermore, I have added defaulted destructors with the right level of protection. Finally, I have renamed my original class `enable_crtp` to `enable_down_cast` because that is precisely what it does: manually enable for static polymporphism what the compiler does automatically for dynamic polymorphism.

Problem

In the following code: ``` template <typename T> class CRTP { public: }; template <int I, typename T> class CRTPInt { public: }; template <template <typename> class T> class Derived : public T<Derived<T>> { public: }; void main() { Derived<CRTP> foo; Derived<CRTPInt<2>> foo2; } ``` How do I write CRPTInt so I can pass in a templatized parameter that will then be continued in the Derived definition? Thanks, Jim

Original source