C++ 自定义列表迭代器错误

C++ Custom List Iterator Errors

我已经开始使用通用数据结构编写自己的库,仅用于教育目的(即:个人实践)。但是,我遇到了一些即使在单链表上也无法自行解决的问题。我不是 C++ 专家,因此我的代码可能有一些问题,所以请不要对我苛刻:)

我试图实现一个 list_node class 来声明和定义一个列表的节点,一个 list_iterator class 作为前向迭代器单链表需要,以及列表 class 应该使用前面提到的 classes 并提供列表的功能。

我现在将附上我在 Visual Studio.

下遇到的代码和错误

list_node.h

/**
 *  list_node.h
 *
 *  @author Raul Butuc.
 *  @version 1.0.0 16/03/2015
 */

#pragma once

#include "list.h"
#include "list_iterator.h"

namespace my_library {

  template <class _Tp>
  class list_node {

    friend class list<_Tp>;
    friend class list_iterator<_Tp>;

    private:
      _Tp m_Node;
      list_node<_Tp> *m_pNext;

      list_node(const _Tp&, list_node<_Tp>*);
      ~list_node();
  };

  template <class _Tp>
  list_node<_Tp>::list_node(const _Tp& node, list_node<_Tp>* next) : m_Node(node), m_pNext(next) {}

  template <class _Tp>
  list_node<_Tp>::~list_node() {
    delete m_pNext;
  }

}

list_iterator.h

/**
 *  list_iterator.h
 *
 *  @author Raul Butuc.
 *  @version 1.0.0 16/03/2015
 */

#pragma once

#include <cassert>
#include <iterator>
#include "list.h"
#include "list_node.h"

namespace my_library {

  template <class _Tp> class list;
  template <class _Tp> class list_node;

  template <class _Tp>
  class list_iterator {

    public:
      // line below has error C2059: syntax error : '<'
      // as well as error C2238: unexpected token(s) preceding ';' 
      friend class list<_Tp>;
      typedef list_iterator<_Tp> iterator;
      typedef size_t size_type;
      typedef _Tp value_type;
      typedef _Tp& reference;
      typedef _Tp* pointer;
      typedef std::forward_iterator_tag iterator_category;
      typedef int difference_type;

      const iterator& operator++();
      const iterator& operator++(int);
      reference operator*();
      pointer operator->();
      bool operator==(const iterator&) const;
      bool operator!=(const iterator&) const;

    private:
      list_node<_Tp>* m_pNode;
      list_iterator(list_node<_Tp>*);

  };

  template <class _Tp>
  list_iterator<_Tp>::list_iterator(list_node<_Tp>* pNode) : m_pNode(pNode) {}

  template <class _Tp>
  const list_iterator<_Tp>::iterator& list_iterator<_Tp>::operator++() {
    assert(m_pNode != NULL);
    m_pNode = m_pNode->m_pNext;
    return *this;
  }

  template <class _Tp>
  const list_iterator<_Tp>::iterator& list_iterator<_Tp>::operator++(int) {
    list_iterator<_Tp>::iterator _tmp = *this;
    ++(*this);
    return _tmp;
  }

  template <class _Tp>
  list_iterator<_Tp>::reference list_iterator<_Tp>::operator*() {
    return m_pNode->m_Node;
  }

  template <class _Tp>
  list_iterator<_Tp>::pointer list_iterator<_Tp>::operator->() {
    return m_pNode;
  }

  template <class _Tp>
  bool list_iterator<_Tp>::operator==(const list_iterator<_Tp>::iterator& other) const {
    return m_pNode == other->m_pNode;
  }

  template <class _Tp>
  bool list_iterator<_Tp>::operator!=(const list_iterator<_Tp>::iterator& other) const {
    return m_pNode != other->m_pNode;
  }

}

list.h

/**
 *  list.h
 *
 *  @author Raul Butuc.
 *  @version 1.0.0 16/03/2015
 */

#pragma once

#include "list_node.h"
#include "list_iterator.h"

namespace my_library {

  template <class _Tp>
  class list {

    public:
      typedef list_iterator<_Tp> iterator;

      list();
      ~list();

      bool empty() const;
      void push_back(const _Tp&);

      iterator begin();
      iterator end();

    private:
      list_node<_Tp>* m_pHead;
      list_node<_Tp>* m_pTail;
  };

  template <class _Tp>
  list<_Tp>::list() : m_pHead(NULL), m_pTail(NULL) {}

  template <class _Tp>
  list<_Tp>::~list() {
    delete m_pHead;
  }

  template <class _Tp>
  bool list<_Tp>::empty() const {
    return m_pHead == NULL;
  }

  template <class _Tp>
  void list<_Tp>::push_back(const _Tp& node) {
    list_node<_Tp>* _node = new list_node<_Tp>(node, NULL);
    if (m_pHead == NULL) {
      m_pHead = _node;
    }
    else {
      m_pTail->m_pNext = _node;
    }
    m_pTail = _node;
  }

  template <class _Tp>
  list<_Tp>::iterator list<_Tp>::begin() {
    return list_iterator<_Tp>(m_pHead);
  }

  template <class _Tp>
  list<_Tp>::iterator list<_Tp>::end() {
    return list_iterator<_Tp>(NULL);
  }

}

test.cpp

/**
 *  Test.cpp
 *
 *  @author Raul Butuc.
 *  @version 1.0.0 16/03/2015
 */

#include <iostream>
#include "list.h"

using std::cout;
using namespace my_library;

int main(int argc, char* argv[]) {
  list<int> list;

  if (list.empty()) {
    std::cout << "List is empty" << "\n";
  }

  for (int i = 0; i < 100; i += 10) {
    list.push_back(i);
  }

  // Here it should allow me to write something like:
  // list<int>::iterator it = list.begin();
  // However, it does not. Could someone please explain
  // why that is so? Sorry if this is due to a naive mistake
  // but I am trying to learn. Thanks again :)
  list_iterator<int> it = list.begin();

  for (; it != list.end(); ++it) {
    std::cout << *it << " ";
  }
  std::cout << "\n";

  system("pause");
  return 0;
}

我在编译时遇到的错误

1>------ Build started: Project: List, Configuration: Debug Win32 ------
1> Test.cpp
1>d:...\list_iterator.h(23): error C2059: syntax error : '<'
1>\d:...\list_iterator.h(43) : see reference to class template instantiation 'my_library::list_iterator<_Tp>' being compiled
1>d:...\list_iterator.h(23): error C2238: unexpected token(s) preceding ';'
1>d:...\list_iterator.h(40): error C2143: syntax error : missing ';' before '<'
1>d:...\list_iterator.h(40): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:...\list_iterator.h(40): error C2238: unexpected token(s) preceding ';'
1>d:...\list_iterator.h(41): error C2061: syntax error : identifier 'list_node'
1>d:...\list_iterator.h(46): error C2061: syntax error : identifier 'list_node'
1>d:...\list_iterator.h(49): warning C4346: 'my_library::list_iterator<_Tp>::iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:...\list_iterator.h(49): error C2143: syntax error : missing ';' before '&'
1>d:...\list_iterator.h(49): error C2065: '_Tp' : undeclared identifier
1>d:...\list_iterator.h(49): error C2923: 'my_library::list_iterator' : '_Tp' is not a valid template type argument for parameter '_Tp'
1>d:...\list_iterator.h(53): error C2509: '++' : member function not declared in 'my_library::list_iterator'
1>
d:...\list_iterator.h(18) : see declaration of 'my_library::list_iterator'
1>d:...\list_iterator.h(53): fatal error C1903: unable to recover from previous error(s); stopping compilation
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

非常感谢您抽出宝贵时间!

编辑:

谢谢 mebob,这确实是主要问题。但是,修复后,我在 list_iterator.h:

中的第 52 行和第 56 行收到一些错误

1>d:\programming - data structures\list\list\list_iterator.h(52): warning C4346: 'my_library::list_iterator::iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\programming - data structures\list\list\list_iterator.h(52): error C2143: syntax error : missing ';' before '&'
1>d:\programming - data structures\list\list\list_iterator.h(52): error C2065: 'T' : undeclared identifier
1>d:\programming - data structures\list\list\list_iterator.h(52): error C2923: 'my_library::list_iterator' : 'T' is not a valid template type argument for parameter 'T'
1>d:\programming - data structures\list\list\list_iterator.h(56): error C2509: '++' : member function not declared in 'my_library::list_iterator'
1>
d:\programming - data structures\list\list\list_iterator.h(21) : see declaration of 'my_library::list_iterator'
1>d:\programming - data structures\list\list\list_iterator.h(56): fatal error C1903: unable to recover from previous error(s); stopping compilation

我也在所有 classes 中从 _Tp 更改为 T(在我的代码中,没有在这里更新)

编辑 2:

即使克服了这些错误,它似乎仍无法编译,这次是因为运算符。

直接涉及到的代码是:

  // other code...
  template <class _Tp>
  typename list_iterator<_Tp>::pointer list_iterator<_Tp>::operator->() {
    return m_pNode;
  }

  template <class _Tp>
  bool list_iterator<_Tp>::operator==(const typename list_iterator<_Tp>::iterator& other) const {
    /*  error C2678: binary '->' : no operator found which takes a left-hand operand
      of type 'const my_library::list_iterator<_Tp>' (or there is no acceptable conversion) */
    return m_pNode == other->m_pNode;
  }
  // other code...

来自 list_iterator.h

你必须有前向声明,像这样:

template <class _Tp> class list;
template <class _Tp> class list_iterator;

在你的朋友声明之前,否则,当编译器看到 friend class list 它不知道需要一个模板参数列表。

至于你的其他错误,你必须使用 const typename list_iterator<_Tp>::iterator& 作为你的类型。任何时候您引用模板化 class(或结构)成员的类型时,您必须事先使用 typename 关键字向编译器阐明您期望它是一个类型。

你的最后一个错误仅仅是因为你试图在常量上调用非常量 operator->()。解决方法是创建它的 const 版本,returns 一个 const 指针。

此外,正如 Neil Kirk 评论的那样,_Tp 可能是一个保留标识符,因此您不应该使用它。