C++ 如何习惯性地编写常量迭代器?
我正在编写一个链表实现,但我一直在研究如何实现一个常量迭代器,该迭代器是通过C++ 如何习惯性地编写常量迭代器?,c++,templates,C++,Templates,我正在编写一个链表实现,但我一直在研究如何实现一个常量迭代器,该迭代器是通过cbegin()与普通迭代器一起访问的。以下是我尝试的解决方案: #include <iostream> using namespace std; template <typename T> class ListNode { public: ListNode<T>* next_; ListNode<T>* prev_; T data_;
cbegin()
与普通迭代器一起访问的。以下是我尝试的解决方案:
#include <iostream>
using namespace std;
template <typename T>
class ListNode {
public:
ListNode<T>* next_;
ListNode<T>* prev_;
T data_;
ListNode():
next_(nullptr),
prev_(nullptr)
{}
};
template <typename T>
class ListIterator
{
typedef ListNode<T> node;
typedef ListNode<T>* pointer;
pointer p_;
public:
ListIterator(pointer p) : p_(p) {}
T& operator*() { return p_->data_; }
};
template<typename T>
class List
{
public:
typedef ListNode<T> node;
typedef ListNode<T>* pointer;
typedef ListIterator<T> iterator;
typedef ListIterator<const T> constIterator;
List() :
head_(nullptr),
tail_(nullptr),
size_(0)
{}
void pushBack(pointer p) {
p->next_ = nullptr;
p->prev_ = nullptr;
if (size_ == 0) {
head_ = p;
} else {
tail_->next_ = p;
p->prev_ = tail_;
}
tail_ = p;
++size_;
}
iterator begin() { return head_; }
iterator end() { return nullptr; }
constIterator cbegin() { return head_; }
constIterator cend() { return nullptr; }
private:
pointer head_;
pointer tail_;
unsigned int size_;
};
class Dog {
public:
int age;
};
int main() {
auto list = List<Dog>();
auto dogNode = ListNode<Dog>();
list.pushBack(&dogNode);
auto b = list.cbegin();
}
#包括
使用名称空间std;
样板
类ListNode{
公众:
ListNode*next;
ListNode*上一个;
T数据;
ListNode():
下一步(nullptr),
上一页(空页)
{}
};
样板
类列表迭代器
{
typedef列表节点;
typedef ListNode*指针;
指针p_;
公众:
ListIterator(指针p):p_Up(p){}
T运算符*(){return p->data}
};
样板
班级名单
{
公众:
typedef列表节点;
typedef ListNode*指针;
typedef列表迭代器迭代器;
typedef列表迭代器;
列表():
头部(空侧),
尾翼(空侧),
尺寸(0)
{}
无效回推(指针p){
p->next_u2;=空PTR;
p->prev_uu=nullptr;
如果(大小=0){
头=p;
}否则{
尾部->下一个->下一个=p;
p->prev=tail;
}
尾部=p;
++大小;
}
迭代器begin(){return head;}
迭代器end(){return nullptr;}
构造函数cbegin(){返回头}
构造函数cend(){return nullptr;}
私人:
指针头;
指针尾;
无符号整数大小;
};
班犬{
公众:
智力年龄;
};
int main(){
自动列表=列表();
自动dogNode=ListNode();
列表。回推(&dogNode);
auto b=list.cbegin();
}
当我尝试运行这个时,我得到了错误
错误:无法将“List::pointer”(又名“ListNode*)类型的返回值转换为函数返回类型
'List::constIterator'(又名'ListIterator')
这个错误对我来说是有意义的,但我无法找到一个不涉及编写单独的ConstListIterator
类的好的解决方法(这是可行的,但从ListIterator
复制所有运算符重载代码感觉是错误的——本示例中省略了大部分内容)
在中,作者使用了将ListIterator
与TNode
参数化的方法,在这种情况下,它将是ListNode
而不是Dog
。这种方法的问题是,操作符*
不能返回实际的Dog
,因为列表迭代器
类不知道typenameDog
。因此,该解决方案只是在数据类型中硬编码,因此您失去了元编程的所有好处
是否有一个技巧可以让它很好地工作,或者我应该只使用一个单独的ConstListIterator
类
谢谢大家! 出现错误的原因是您试图从返回类型为conditerator
的函数返回类型为ListNode*
的head
为了回答您的问题,迭代器
和常量迭代器
之间的唯一区别是常量迭代器
返回容器的值类型
的常量引用,而不仅仅是引用。因此,将const T
作为模板参数传递应该会产生所需的功能。由于运算符*
返回T&
,如果T
改为const T
,则返回const T&
,这是正确的。您遇到的问题似乎是因为您从迭代器
函数返回了错误的类型,如上所述
您的迭代器函数应该如下所示:
iterator begin() { return iterator{head_}; }
iterator end() { return iterator{nullptr}; }
constIterator cbegin() { return constIterator{head_}; }
constIterator cend() { return constIterator{nullptr}; }
这将返回使用指针head
和nullptr
构造的iterator
和conditerator
对象,这正是您想要的
用于迭代器的模板参数(列表的值类型
)是正确的。将节点类型作为迭代器的模板参数是合理的,并且允许
using constIterator=ListIterator<const ListNode<T>>;
*p
的常数传递到数据,然后传递到返回类型
在C++14之前
在C++11中,可以为ListNode
配备
using value_type=T;
并使用类型特征,如is_const
和conditional
从const ListNode
派生const T
在C++03中,您可以直接为此编写基于SFINAE的trait。编辑以反映该事实。再次编辑。谢谢
using value_type=T;