문제

In one of my projects I'm using the same CRTP approach (deriving from enable_crtp) as in Answer 1 here: How do I pass template parameters to a CRTP?

However I have the need to derive from the derived classes too. Is there any way to make this work with out falling back to just static_cast the this pointer but by using the self() method from the Enable CRTP base class?

#include "EnableCRTP.h"

template<typename DERIVED>
class BASE : public EnableCRTP<DERIVED>
{
    friend DERIVED;
public:
    void startChain()
    {
        self()->chain();
    }
};

template<typename DERIVED>
class Derived1 : public BASE<Derived1<DERIVED> >
{
public:
    void chain()
    {
        std::cout << "Derived1" << std::endl;

        //self()->chain2(); <- compile Error
        static_cast<DERIVED*>(this)->chain2(); // <-Works
    }
};

class Derived2 : public Derived1<Derived2>
{
public:
    void chain2()
    {
        std::cout << "Derived2" << std::endl;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Derived2 der;    
    der.startChain();    
    return 0;
}
도움이 되었습니까?

해결책

You can give the most-derived class as the template parameter to the CRTP base class, so that it will have access to all its members. Instead of

template<typename DERIVED>
class Derived1 : public BASE<Derived1<DERIVED> >

Use:

template<typename DERIVED>
class Derived1 : public BASE<DERIVED>

There are also other issues with your code. For example, you can't directly call self() like you do because the compiler doesn't know that self is a member of the base class (which is dependent on a template parameter). Instead, call this->self(). See this FAQ entry.

다른 팁

To do what you want, you only pass the most derived class via the CRTP. In this case, you need to change the definition of Derived1 to the following:

template<typename DERIVED>
class Derived1 : public BASE< DERIVED >
{
public:
    void chain()
    {
        std::cout << "Derived1" << std::endl;

        this->self()->chain2(); // should work now
        //static_cast<DERIVED*>(this)->chain2(); // <-Works
    }
};

Also, when using CRTP with class hierarchies, it's usually better to set up your hierarchy such that a class is either designed to be derived from (and is hence a template that is passed the DERIVED class), or is a leaf of the hierarchy and is not derived from. These leaf classes do not have to be templates at all.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top