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
可能是一个保留标识符,因此您不应该使用它。
我已经开始使用通用数据结构编写自己的库,仅用于教育目的(即:个人实践)。但是,我遇到了一些即使在单链表上也无法自行解决的问题。我不是 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
可能是一个保留标识符,因此您不应该使用它。