缺少模板参数

时间:2011-09-27 04:09:25

标签: c++ templates

这是家庭作业的一部分,但我尽可能地减少了问题。提供的代码并没有真正做任何事情,只是创建一些对象,所以我归结为纯语言问题。

我认为我的问题是:模板类是否可以创建具有相同模板类型的另一个类?

分配是使用main.cc:

#include "linkedlist.hh"

int main()
{
    LinkedList<int> aList;
    ListIterator elements = aList.iterator(); // if commented out, then no error
}

我对linkedlist.hh有以下内容:

template <typename T> class LinkedList;
template <typename T> class ListIterator;

template <typename T>
    class LinkedList {
    public:
    ListIterator<T> iterator();
};

template <typename T>
    ListIterator<T> LinkedList<T>::iterator() {
    return new ListIterator<T>;
}

template <typename T>
    class ListIterator {
};

使用g ++ - 4.6给出以下错误:

main.cc: In function ‘int main()’:
main.cc:6:18: error: missing template arguments before ‘elements’
main.cc:6:18: error: expected ‘;’ before ‘elements’

与clang ++ - 2.9相似的错误:

main.cc:6:5: error: cannot refer to class template 'ListIterator' without a
      template argument list
    ListIterator elements = list.iterator();
    ^
In file included from main.cc:1:
./linkedlist.hh:16:11: note: template is declared here
    class ListIterator {

更新:是的,如果我可以更改main.cc,那么我可以执行以下操作,但我不认为这就是作业。

main.cc

#include "linkedlist.hh"

int main()
{
    LinkedList<int> aList;
    ListIterator<int> elements = aList.iterator();
}

和linkedlist.hh

template <typename T> class LinkedList;
template <typename T> class ListIterator;

template <typename T>
    class LinkedList {
    public:
    ListIterator<T> iterator();
};

template <typename T>
    ListIterator<T> LinkedList<T>::iterator() {
    ListIterator<T> anIterator;
    return anIterator;
}

template <typename T>
    class ListIterator {
};

5 个答案:

答案 0 :(得分:1)

不应该是ListIterator<int>

答案 1 :(得分:0)

ListIterator是一个模板,显然你必须给它一个模板参数。试试ListIterator<int>

答案 2 :(得分:0)

这就是你如何实现一个泛型迭代器,它可以在迭代器上对任何类型的元素列表进行一些基本操作,但这很不寻常。

struct ListIteratorBase {
  virtual void advance() = 0;
  virtual bool atEnd() const = 0;
  virtual ~ListIteratorBase() { }
};

template <typename T>
struct BasicListIterator : ListIteratorBase {
  virtual void advance(); // implement this
  virtual bool atEnd() const;  // and this
  T value() const; // and this
};

struct ListIterator {
  template <typename T> ListIterator(BasicListIterator<T> &iter)
  : iter_ptr(new BasicListIterator<T>(iter))
  {
  }

  ~ListIterator() { delete iter_ptr; }

  void operator++() { iter_ptr->advance(); }
  bool atEnd() const { return iter_ptr->atEnd(); }

  // Method to get the value for a particular type.  It is up to the caller to
  // make sure the type is right at runtime.
  template <typename T>
  T get<>() const
  {
    BasicListIterator<T> *p = dynamic_cast<BasicListIterator<T> *>(iter_ptr);
    assert(p);
    return p->value();
  }

  ~ListIterator() { delete iter_ptr; }

  ListIteratorBase *iter_ptr;
};

然后你需要

template <typename T>
BasicListIterator<T> LinkedList<T>::iterator() { ... }

答案 3 :(得分:0)

为此,在C ++ 11中,添加了 auto 指令

请参阅Type inference

答案 4 :(得分:0)

重命名ListIterator并将typedef MyListIterator<int> ListIterator;添加到标题的末尾。然后主代码将不加修改地工作。

这只是使这个特定代码工作的一个技巧。您不能使符合标准库的迭代器不依赖于模板或模板。如果您不必创建符合标准库的迭代器,那么您可以使用一种称为类型擦除的技术(Vaughn Cato的答案),但这是一个相当高级的主题。