如何在类层次结构中处理CRTP?

时间:2012-11-19 12:16:01

标签: c++ templates crtp

在我的一个项目中,我使用相同的CRTP方法(源自enable_crtp),如答案1所示:How do I pass template parameters to a CRTP?

但是我也需要从派生类派生。有没有办法让这个工作没有回到static_cast这个指针但是通过使用Enable CRTP基类中的self()方法?

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

2 个答案:

答案 0 :(得分:1)

您可以将派生程度最高的类作为模板参数提供给CRTP基类,以便它可以访问其所有成员。而不是

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

使用:

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

您的代码还存在其他问题。例如,您无法直接调用self(),因为编译器不知道self是基类的成员(依赖于模板参数)。相反,请致电this->self()。请参阅this FAQ entry

答案 1 :(得分:0)

要执行您想要的操作,您只能通过CRTP传递派生程度最高的类。在这种情况下,您需要将Derived1的定义更改为以下内容:

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

此外,当使用带有类层次结构的CRTP时,通常最好设置层次结构,使得类可以设计为派生自(并因此是传递DERIVED类的模板),或者是层次结构并非源自。这些叶子类根本不必是模板。