застрял в цикле требования шаблона - PullRequest
2 голосов
/ 21 октября 2009

У меня есть класс, который использует шаблон «надстройки» для добавления дополнительных функций, как показано ниже:

template< class T >
class AddOn_A
{
public: 
    int SomeFuncA()
    {
        T* pT = static_cast< T* >( this );
        return pT->DoSomething() + 1;
    };
};

class CMyClass : public AddOn_A< CMyClass >
{
public:
    int DoSomething()
    {
        return 100;
    };
};

int _tmain(int argc, _TCHAR* argv[])
{
    CMyClass A;
    _ASSERT( A.SomeFuncA() == 101 );

    return 0;
}

Теперь я хотел бы расширить это так, чтобы CMyClass мог принимать различные надстройки, такие как AddOn_B.

template< class T >
class AddOn_B
{
public: 
    int SomeFuncB()
    {
        T* pT = static_cast< T* >( this );
        return pT->DoSomething() + 2;
    };
};

template< class AddOn >
class CMyClass : public AddOn
{
public:
    int DoSomething()
    {
        return 100;
    };
};

int _tmain(int argc, _TCHAR* argv[])
{
    // error C3203: 'AddOn_A' : unspecialized class template can't be used as a template argument for template parameter 'AddOn', expected a real type
    // error C2955: 'AddOn_A' : use of class template requires template argument list
    CMyClass< AddOn_A > A;
    _ASSERT( A.SomeFuncA() == 101 );

    // same errors here
    CMyClass< AddOn_B > B;
    _ASSERT( B.SomeFuncB() == 102 );

    return 0;
}

К сожалению, каждый Add_On требует CMyClass в качестве параметра шаблона, который требует Add_On и т. Д ... Я в цикле требований.

Есть ли какая-то магия шаблонов, которую я могу использовать для получения нужной мне функциональности? Есть ли лучший способ сделать это?

Спасибо, PaulH

Ответы [ 3 ]

2 голосов
/ 21 октября 2009

Если я правильно понял ваш вопрос (не уверен), то вам нужен аргумент шаблона шаблона:

template< template<class> class AddOn >
class CMyClass : public AddOn< CMyClass<AddOn> > {
  // ...
};
0 голосов
/ 21 октября 2009

Почему вы не можете просто использовать:

CMyClass< AddOn_A<CMyClass> > A;
_ASSERT( A.SomeFuncA() == 101 );
0 голосов
/ 21 октября 2009

Очевидно, вы пытаетесь использовать знаменитый Любопытно повторяющийся шаблон шаблона .

Я не уверен в том, что именно вы хотите сделать, но вы можете избежать неприятностей с другим решением:

Что делать, если вы использовали два класса:

 class Base {};

 class MyClass: public AddOn<Base> {};

Вы также можете использовать подход, основанный на политике:

 class PolicyA_A {};
 class PolicyA_B {};

 class PolicyB_A {};
 class PolicyB_B {};

 template <class PolicyA, class PolicyB>
 class MyClass: private PolicyA, private PolicyB {};

 typdef MyClass<PolicyA_A, PolicyB_A> MyClassAA;

Идея состоит в том, чтобы делегировать часть работы политикам для повышения гибкости.

И последнее, но не менее важное: вы можете использовать Decorator подход:

 class Base {};

 template <class T>
 class AddOn_A: public T {};

 class MyClass: public AddOn_A< AddOn_B< Base > > {};

Позволяет избавиться от виртуального наследования, подавляя множественное наследование и делая иерархию линейной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...