Шаблонный список шаблонных объектов в C ++ - PullRequest
1 голос
/ 09 августа 2010

Я пытаюсь создать список объектов, где каждый объект также хранит «владение» - т. Е. Он знает, какой список содержит его.

В ситуации, не связанной с шаблоном, это просто:

class FooList;  // forward declaration

class FooItem
{
  public:
     FooList *owner;
  ...
};

class FooList: private std::list<FooItem>
{
  ...
};

Однако класс списка - это шаблон, основанный на содержании типа объекта, и я изо всех сил пытаюсь решить, как это указать.Я считаю, что класс FooItem теперь должен быть шаблоном, потому что тип 'owner' может варьироваться:

template <class E> class FooItem
{
  public:
     std::list<E> *owner;
};

template <class E> class FooList: private std::list<E>
{
  ...
};

Но, учитывая мои два шаблона, как я могу определить новые типы, которые я хочу?Ниже приведен фрагмент, который, как мне кажется, мне нужен, но он дает "error: Multiple declaration for BarItem".

class BarItem;

typedef FooList<BarItem> BarList;
typedef FooItem<BarList> BarItem;

РЕДАКТИРОВАТЬ:

Спасибо тем, кто указал навыпуск std::list<E> вместо std::list<FooItem<E> >


РЕДАКТИРОВАТЬ 2: Переименованные классы в Base, Derived, BaseList, DerivedList.

Моя настоящая проблема заключалась в «циклическом определении типа».Я думаю, что после еще нескольких поворотов я сделаю то, что мне нужно.Он создает «настоящий» класс BarItem, а не просто typedef, но, кажется, по крайней мере сейчас компилируется.

template <class E> class BaseList; // forward declaration

template <class E> class Base
{
  public:
     BaseList< Base<E> > *owner;
};

template <class E> class BaseList: private std::list< E >
{
};

// typedef Base<BaseList<Derived> > Derived;  //This won't compile, unsurprisingly.

class Derived : public Base < BaseList<Derived> >  // Surprisingly, this seems to.
{
...
};

typedef BaseList<Derived> DerivedList;

Кажется ли это имеет смысл?Это обычная идиома или что-то ужасное?

Ответы [ 3 ]

4 голосов
/ 09 августа 2010

Вы уверены, что не хотите:

template <class E> class FooItem
{
  public:
     std::list< FooItem<E> > *owner; // owned by a list of FooItem<E>, not raw E
};

template <class E> class FooList: private std::list< FooItem<E> > // is a list of FooItem<E>, not raw E
{
  ...
};

Ошибка, которую вы получаете, заключается в том, что вы объявляете класс BarItem вперед, но позже пытаетесь переопределить это имя, используя typedef. Не уверен, что вы пытаетесь достичь, но вам нужно ввести третье имя. Может быть, вы имели в виду:

class Bar;
typedef FooItem<Bar> BarItem;
typedef FooList<Bar> BarList;

РЕДАКТИРОВАТЬ: новый код, который вы разместили, конечно, компилируется, но кажется очень неловким (с одной стороны, наименование кажется действительно запутанным) Возможно, вам следует задать новый вопрос с более конкретным примером того, почему вы думаете, что вам нужен «элемент, который является элементом списков» и посмотреть, могут ли другие придумать менее неудобный дизайн.

3 голосов
/ 09 августа 2010

Если вы просто хотите обобщить свой первый подход к шаблонному FooItem классу, он будет выглядеть так:

template <class E> class FooList; // forward declaration

template <class E> class FooItem
{
  public:
     FooList<E> *owner;
  ...
};

template <class E> class FooList: private std::list< FooItem<E> >
{
  ...
};

Если это не то, что вы хотите, я не уверен, что именно вы пытаетесь сделать.

3 голосов
/ 09 августа 2010

Является ли последний набор typedef операторов правильным?Вы опубликовали это:

class BarItem;

typedef FooList<BarItem> BarList;
typedef FooItem<BarList> BarItem;

Это несколько рекурсивно, верно?Первое утверждение говорит, что есть класс BarItem, который существует в другом месте.Второе утверждение говорит, что тип FooList<BarItem> (список BarItem объектов) также может упоминаться как BarList.Третье утверждение говорит, что тип FooItem<BarList> также может упоминаться как BarItem, но BarItem уже был определен как тип оператором class BarItem.

Итак, вы говорите, что BarItem - это тип all для себя (с помощью оператора class), но вы также говорите, что BarItem является псевдонимом для типа FooItem<BarList>.Отсюда и конфликт.

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