C ++ шаблонная рекурсия - как решить? - PullRequest
1 голос
/ 27 октября 2009

Я снова застрял с шаблонами.

скажем, я хочу внедрить систему guicell. каждый гицелл может содержать несколько дочерних гизелл. пока что, такая древовидная структура. в std-c ++ я бы пошел на sthg. как:

template <typename T>
class tree
{
public:

    void add (T *o)     { _m_children.push_back (o); }
    void remove (T *o)  { ... };

    list<T*> _m_children;
};

class _cell : public tree<_cell>
{
public:
    _cell ()            { x = 0; y =0; }
    long                x,y;
};

Но теперь я хочу пойти дальше и сделать ссылки на ячейки, если кодер этого пожелает. поэтому я в основном реализую для этой цели класс refTree, который также принимает только указатели (_cell *) в качестве входных данных.

template <typename T>
class refTree
{
public:
   void add (T *o)      { _ref<T> r = o;  _m_children.push_back (r);  }
   void remove (T *o)       { ... }

   list<_ref<T> > _m_children;
};

Также это все еще работает нормально. используя

class _cell : public refTree<_cell>
{
   :
};

без изменений в коде пользователя, но все добавленные _cell * теперь ссылаются перед добавлением в дерево.

Хорошо, но теперь я хочу иметь возможность выбирать на _cell - уровне, какую реализацию дерева-шаблонов использовать. Таким образом, это означает, что я должен сделать _cell - класс шаблоном класса, который принимает класс шаблона в качестве параметра (выбранный шаблон дерева).

template <template <typename> class __TyTree = tree>
class Cell : public __TyTree <Cell>     // cannot work - no question, Cell expects input
{
};

И здесь мы получили рекурсивную проблему - конечно, компилятор не может решить эту проблему, потому что Cell ожидает дерево-параметр, который ожидает параметр простого типа (который должен быть Cell ofc. Ожидает дерево-параметр что ожидает простого ....).

Вы получите картину - как правильно решить эту проблему?

Ответы [ 2 ]

5 голосов
/ 27 октября 2009

рекурсии нет. Аргумент шаблона для Cell равен __TyTree, а не __TyTree<Cell>.

template <template <typename> class __TyTree = tree>
class Cell : public __TyTree <Cell<__TyTree> >
{
};

int main()
{
   Cell          mycell0; // error
   Cell<>        mycell1; // ok. tree is used
   Cell<tree>    mycell2;
   Cell<refTree> mycell3;
}

P.S. Вы не должны использовать два ведущих подчеркивания в __TyTree, поскольку они зарезервированы для целей реализации стандартом C ++.

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

У вас есть две отдельные проблемы: что находится в ячейке и как ячейки связаны друг с другом. Для этого вам нужно использовать две отдельные структуры данных. Другими словами, правильная ссылка на разрыв - это наследование ячейки от дерева. Небольшое количество памяти, которое вы сохраняете, не стоит - отбросьте «навязчивый» подход. Ячейка не должна знать, как дерево ее держит.

...