Замена макросов определения класса шаблонами

class ListItem
{
    ListItem*   GetPrev     ();
    ListItem*   GetNext     ();
    // ... and many more
};

class One : public ListItem
{
    One*    GetPrev () { return static_cast<One*>(ListItem::GetPrev()); }
    One*    GetNext () { return static_cast<One*>(ListItem::GetNext()); }
    // ... and many more overrides
};

class Two : public ListItem
{
    Two*    GetPrev () { return static_cast<Two*>(ListItem::GetPrev()); }
    Two*    GetNext () { return static_cast<Two*>(ListItem::GetNext()); }
    // ... and many more overrides
};

class Object : public One, public Two
{
};

Цель этого состоит в том, чтобы объект класса вставлялся в два или более различных списка. Мой вопрос в том, как я могу шаблон один и два? Поскольку имя класса также отображается как тип, возможно ли это вообще? У меня это покрыто макросами, но можно ли это сделать с помощью шаблонов? Я не против, если структура кода немного изменится, но можно ли это сделать без макросов?

2 ответа

  1. Конечно, вы можете сделать ListItemшаблон:

    template<class T>
    class ListItem
    {
        T*   GetPrev     ();
        T*   GetNext     ();
        // ... and many more
    };
    
    class One : public ListItem<One>
    

    Это любопытно повторяющийся шаблон шаблона.

  2. Вы можете использовать любопытно повторяющийся шаблон шаблона и даже все еще иметь ListItemродителя. Но, пожалуйста, подумайте об использовании некоторых std::vectorилиstd::list, нет необходимости изобретать списки шаблонов… Тем более, что звонки с Objectуровня должны были бы выглядеть именно так:

    Object o;
    One* prev = o.One::GetPrev();
    

    Рабочий код ( http://ideone.com/dbmwFZ):

    struct ListItem
    {
        ListItem*   GetPrev     ();
        ListItem*   GetNext     ();
        // ... and many more
    };
    
    template <typename T>
    struct ListItemT : ListItem
    {
        T*    GetPrev () { return static_cast<T*>(ListItem::GetPrev()); }
        T*    GetNext () { return static_cast<T*>(ListItem::GetNext()); }
    };
    
    struct One : ListItemT<One>
    {
    };
    
    class Two : public ListItemT<Two>
    {
    };
    
    class Object : public One, public Two
    {
    };