【问题标题】:C++ Custom List Iterator ErrorsC++ 自定义列表迭代器错误
【发布时间】:2015-05-19 07:51:54
【问题描述】:

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

我试图实现一个 list_node 类,它声明和定义一个列表的节点,一个 list_iterator 类,它充当单链表所需的前向迭代器,以及应该使用的 list 类前面提到的类,并提供列表的功能。

我现在将附上代码和我在 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>----- 构建开始:项目:列表,配置:调试 Win32 ------
1> Test.cpp
1>d:...\list_iterator.h(23): 错误 C2059: 语法错误: ' 1>\d:. ..\list_iterator.h(43):见 引用类模板实例化 'my_library::list_iterator<_tp>' 正在编译
1>d:...\list_iterator.h(23): 错误 C2238: 意外令牌 前面的';'
1>d:...\list_iterator.h(40): 错误 C2143: 语法 错误:缺少';'在 ' 1>d:...\list_iterator.h(40) 之前: 错误 C4430:缺少类型说明符 - 假定为 int。注意:C++ 没有 支持 default-int
1>d:...\list_iterator.h(40): error C2238: ';' 之前的意外标记
1>d:...\list_iterator.h(41): 错误 C2061:语法错误:标识符“list_node”
1>d:...\list_iterator.h(46): 错误 C2061: 语法错误: 标识符 'list_node'
1>d:...\list_iterator.h(49): 警告 C4346: 'my_library::list_iterator<_tp>::iterator' : 从属名称不是 type
1> 带有'typename'前缀以表示类型
1>d:...\list_iterator.h(49): 错误 C2143: 语法错误: 缺少';' 在'&'
1>d:...\list_iterator.h(49) 之前:错误 C2065:'_Tp': 未声明的标识符
1>d:...\list_iterator.h(49): 错误 C2923: 'my_library::list_iterator' : '_Tp' 不是有效的模板类型 参数“_Tp”的参数
1>d:...\list_iterator.h(53): 错误 C2509:“++”:未在中声明的成员函数 'my_library::list_iterator'
1>
d:...\list_iterator.h(18) : 见声明 'my_library::list_iterator'
1>d:...\list_iterator.h(53): 致命 错误 C1903:无法从先前的错误中恢复;停止 编译
========== 构建:0 成功,1 失败,0 最新,0 跳过 ==========

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

编辑:

感谢 mebob,这确实是主要问题。但是,在修复之后,我在 list_iterator.h 的第 52 行和第 56 行遇到了一些错误:

1>d:\programming - 数据结构\list\list\list_iterator.h(52): 警告 C4346:“my_library::list_iterator::iterator”:依赖 name 不是类型
1> 前缀以 'typename' 表示 类型
1>d:\programming - 数据 结构\列表\列表\list_iterator.h(52):错误C2143:语法错误: 失踪 ';'在“&”之前
1>d:\programming - 数据 结构\列表\列表\list_iterator.h(52):错误C2065:'T': 未声明的标识符
1>d:\programming - 数据 结构\列表\列表\list_iterator.h(52):错误C2923: 'my_library::list_iterator' : 'T' 不是有效的模板类型 参数“T”的参数
1>d:\programming - data 结构\列表\列表\list_iterator.h(56):错误C2509:'++':成员 函数未在“my_library::list_iterator”中声明
1>
d:\programming - 数据结构\list\list\list_iterator.h(21):见 'my_library::list_iterator'
1>d:\programming 的声明 - 数据结构\list\list\list_iterator.h(56):致命错误 C1903: 无法从以前的错误中恢复;停止编译

我还在所有类中从 _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

【问题讨论】:

  • 如果您突出显示导致错误的第一行会很好。
  • 抱歉,我没有意识到行号没有打开。给我一分钟。
  • 您可能正在使用保留标识符stackoverflow.com/questions/228783/…
  • @NeilKirk 我认为你是对的,但我认为这不是编译错误的原因。

标签: c++ templates data-structures


【解决方案1】:

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

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

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

至于您的其他错误,您必须使用const typename list_iterator&lt;_Tp&gt;::iterator&amp; 作为您的类型。每当您引用属于模板化类(或结构)成员的类型时,您必须事先使用 typename 关键字向编译器说明您期望它是一个类型。

您的最后一个错误仅仅是因为您试图在 const 上调用非 const operator-&gt;()。解决方法是只创建一个返回 const 指针的 const 版本。

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

【讨论】:

  • @MasterKoder 您必须使用 const typename list_iterator&lt;_Tp&gt;::iterator&amp; 作为您的类型。每当您引用属于模板类(或结构)成员的类型时,您必须事先使用 typename 关键字向编译器说明您期望它是一种类型。
  • @MasterKoder 据我所知,这是因为不同的专业化可以将某个名称定义为一个类型和另一个值,但是在解析时编译器必须知道哪个是的。
  • @MasterKoder 问题是您没有const 版本的operator-&gt;(),但您在const 合格的list_iterator&lt;_Tp&gt;::iterator&amp; 上调用它。您必须创建另一个版本的 operator-&gt;(),它是 const 限定的,并返回 const 指针
  • 抱歉,没错。我应该更加小心使用 const :)
  • @MasterKoder isocpp.org/wiki/faq/const-correctness#const-member-fns 。但是为了节省您一些时间,您基本上必须这样做:const [pointer type here] operator-&gt;() const。我建议您查看该常见问题解答页面:)
猜你喜欢
  • 2015-11-19
  • 1970-01-01
  • 2014-05-23
  • 2012-09-07
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多