C ++中模板化对象的模板化列表

时间:2010-08-09 16:31:13

标签: c++ templates

我正在尝试创建一个对象列表,其中每个对象也存储“所有权” - 即,它知道哪个列表包含它。

在非模板情况下,它很简单:

class FooList;  // forward declaration

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

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

但是,list类是一个模板,基于包含的对象类型,我正在努力弄清楚如何指定它。我认为FooItem类现在需要成为模板,因为“所有者”的类型可能会有所不同:

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.

我真正的问题是'循环typedef'。经过一些修补,我认为这将做我需要的。它创建了一个“真正的”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 个答案:

答案 0 :(得分:4)

你确定你不想要:

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;

编辑:您发布的新代码肯定会编译,但看起来很尴尬(一方面,命名看起来真的很混乱)。也许你应该用一个更具体的例子来问一个新的问题,为什么你认为你需要一个“项目是一个自己的列表项目”,看看其他人是否可以提出一个不那么尴尬的设计。

答案 1 :(得分:3)

最后一组typedef语句是否正确?你发布了这个:

class BarItem;

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

这有点递归,对吧?第一个声明说在其他地方存在一个类BarItem。第二个语句说类型FooList<BarItem>BarItem个对象的列表)也可以称为BarList。第三个语句表示类型FooItem<BarList>也可以称为BarItem,但BarItem已经被class BarItem语句定义为类型。

所以你说BarItem是一个自己的类型(通过class语句),但你也说BarItem是类型的别名{ {1}}。因此,冲突。

答案 2 :(得分:3)

如果您只想概括您对模板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> >
{
  ...
};

如果那不是你想要的,我不确定你到底想要做什么。