0

私のプロジェクトの1つで、enable_crtpここの回答1と同じCRTPアプローチ(から派生)を使用しています:テンプレートパラメーターを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;
}
4

2 に答える 2

1

最も派生したクラスをテンプレート パラメーターとして CRTP 基本クラスに指定すると、すべてのメンバーにアクセスできるようになります。それ以外の

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

使用する:

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

コードには他にも問題があります。たとえば、コンパイラはそれが基本クラス (テンプレート パラメーターに依存する) のメンバーであるself()ことを認識しないため、直接呼び出すことはできません。self代わりに、 を呼び出しますthis->self()この FAQ エントリを参照してください。

于 2012-11-19T12:30:02.180 に答える
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 クラスに渡されるテンプレートである) ように階層を設定するか、階層のリーフであり、から派生したものではありません。これらのリーフ クラスは、テンプレートである必要はまったくありません。

于 2012-11-19T12:30:13.970 に答える