我试图学习像迭代器一样编写stl,因为我编写了一个简单的循环数组并在其中添加了一个迭代器。请查看代码底部以查看问题。
template<typename T, int N>
class RingQueue{
T * _marray;
int _mbegin;
int _msize;
public:
RingQueue(){
_marray = new T[N];
_mbegin = 0;
_msize= 0;
}
void push_back(const T& val){
if(_msize!=N){
_marray[(_mbegin+_msize)%N] = val;
_msize++;
}
else
throw "Queue Full";
}
T pop_front(){
if(_msize!=0){
T&val = _marray[_mbegin];
_mbegin = (_mbegin+1)%N;
_msize--;
return val;
}
else
throw "Queue Empty";
}
class iterator{
RingQueue<T,N>* _container;
int _idx;
public:
iterator(RingQueue<T,N>* container,int idx):_container(container){
_idx = idx;
}
bool operator==(iterator &rhs){
return (this->_container==rhs._container && this->_idx == rhs._idx);
}
bool operator!=(iterator &rhs){
return !(*this==rhs);
}
T operator*(){
if(_container->_msize>0&&_idx<_container->_msize){
return _container->_marray[(_container->_mbegin+_idx)%N];
}
}
iterator& operator++(){
if(_container->_msize ==0){
*this = _container->end();
return *this;
}
if(_idx==_container->_msize){
*this = _container->end();
return *this;
}
_idx++;
return *this;
}
};
iterator begin(){
return iterator(this,0);
}
iterator end(){
return iterator(this,_msize);
}
};
int current=0;
int gen(){
return current++;
}
int curr_op=0;
int operation(){
return 2*(curr_op++&1)-1;
}
int main(){
RingQueue<int,10> ring;
vector<int> v(9),op(9);
generate(v.begin(),v.end(),gen);
random_shuffle(v.begin(),v.end());
copy(v.begin(),v.end(),ostream_iterator<int>(cout," "));
cout<<endl;
generate(op.begin(),op.end(),operation);
random_shuffle(op.begin(),op.end());
// copy(op.begin(),op.end(),ostream_iterator<int>(cout," "));
cout<<endl;
for(vector<int>::iterator itv = v.begin();itv!=v.end();itv++){
try{
ring.push_back(*itv);
}catch(const char * e){
cout<<*itv<<e<<endl;
}
}
//works
RingQueue<int,10>::iterator ite = ring.end();
for(RingQueue<int,10>::iterator it = ring.begin(); it!=ite; ++it){
cout<<*it<<endl;
}
// doesn't work
for(RingQueue<int,10>::iterator it = ring.begin(); it!=ring.end(); ++it){
cout<<*it<<endl;
}
return 0;
}
当我编译不起作用的部分时,g ++转储以下错误
ringqueue.cpp: In function ‘int main()’:
ringqueue.cpp:112: error: no match for ‘operator!=’ in ‘it != ring.RingQueue<T, N>::end [with T = int, int N = 10]()’
ringqueue.cpp:48: note: candidates are: bool RingQueue<T, N>::iterator::operator!=(RingQueue<T, N>::iterator&) [with T = int, int N = 10]
工程部分无缝编译,编译时无需工作部分。有人可以解释我的错误。
答案 0 :(得分:9)
我认为问题在于以下几点:
bool operator==(iterator &rhs){
return (this->_container==rhs._container && this->_idx == rhs._idx);
}
bool operator!=(iterator &rhs){
return !(*this==rhs);
}
这里的问题是这些函数接受对其参数的左值引用。这意味着如果您尝试将rvalue(例如,从函数返回的临时对象)传递到这些运算符中,您将收到编译时错误,因为引用无法绑定到临时对象。要解决此问题,请将参数更改为const引用:
bool operator==(const iterator &rhs){
return (this->_container==rhs._container && this->_idx == rhs._idx);
}
bool operator!=(const iterator &rhs){
return !(*this==rhs);
}
因为const引用可以绑定到temporaries,或者让它们按值获取它们的参数:
bool operator==(iterator rhs){
return (this->_container==rhs._container && this->_idx == rhs._idx);
}
bool operator!=(iterator rhs){
return !(*this==rhs);
}
无论你做出哪种选择,你都应该标记这些函数const
,因为它们不会改变接收者对象。
希望这有帮助!
答案 1 :(得分:0)
#include <vector>
#include <iostream>
#include <sstream>
#include <iterator>
using namespace std;
template<typename T, int N>
class RingQueue{
T * _marray;
int _mbegin;
int _msize;
public:
RingQueue(){
_marray = new T[N];
_mbegin = 0;
_msize= 0;
}
void push_back(const T& val){
if(_msize!=N){
_marray[(_mbegin+_msize)%N] = val;
_msize++;
}
else
throw "Queue Full";
}
T pop_front(){
if(_msize!=0){
T&val = _marray[_mbegin];
_mbegin = (_mbegin+1)%N;
_msize--;
return val;
}
else
throw "Queue Empty";
}
class iterator{
RingQueue<T,N>* _container;
int _idx;
public:
iterator(RingQueue<T,N>* container,int idx):_container(container){
_idx = idx;
}
bool operator==(iterator rhs){ // XXX do not pass it as a reference
return (this->_container==rhs._container && this->_idx == rhs._idx);
}
bool operator!=(iterator rhs){ // XXX do not pass it as a reference
return !(*this==rhs);
}
T operator*(){
if(_container->_msize>0&&_idx<_container->_msize){
return _container->_marray[(_container->_mbegin+_idx)%N];
}
throw "XXX"; // XXX missing return statement
}
iterator& operator++(){
if(_container->_msize ==0){
*this = _container->end();
return *this;
}
if(_idx==_container->_msize){
*this = _container->end();
return *this;
}
_idx++;
return *this;
}
};
iterator begin(){
return iterator(this,0);
}
iterator end(){
return iterator(this,_msize);
}
};
int current=0;
int gen(){
return current++;
}
int curr_op=0;
int operation(){
return 2*(curr_op++&1)-1;
}
int main(){
RingQueue<int,10> ring;
vector<int> v(9),op(9);
generate(v.begin(),v.end(),gen);
random_shuffle(v.begin(),v.end());
copy(v.begin(),v.end(),ostream_iterator<int>(cout," "));
cout<<endl;
generate(op.begin(),op.end(),operation);
random_shuffle(op.begin(),op.end());
// copy(op.begin(),op.end(),ostream_iterator<int>(cout," "));
cout<<endl;
for(vector<int>::iterator itv = v.begin();itv!=v.end();itv++){
try{
ring.push_back(*itv);
}catch(const char * e){
cout<<*itv<<e<<endl;
}
}
for(RingQueue<int,10>::iterator it = ring.begin(); it!=ring.end(); ++it){
cout<<*it<<endl;
}
return 0;
}
代码正常运行。寻找XXX标记;)
答案 2 :(得分:0)
为自定义容器编写迭代器时,您可能会发现使用boost::iterator_facade会很有帮助。它是一个库,允许您仅定义迭代器的基本操作(增量,取消引用和相等比较,以及,如果适用,减量和前进),并通过提供所有必需的运算符为您填充空白。以下是使用boost :: iterator_facade:
的迭代器的外观class iterator : public boost::iterator_facade<iterator, T, boost::forward_traversal_tag>{
RingQueue<T,N>* _container;
int _idx;
public:
iterator(RingQueue<T,N>* container,int idx):_container(container){
_idx = idx;
}
bool equal(const iterator &rhs) const {
return (this->_container==rhs._container && this->_idx == rhs._idx);
}
T dereference() const {
if(_container->_msize>0&&_idx<_container->_msize){
return _container->_marray[(_container->_mbegin+_idx)%N];
}
}
void increment(){
if(_container->_msize ==0)
*this = _container->end();
else if(_idx==_container->_msize)
*this = _container->end();
else
_idx++;
}
};
boost::forward_traversal_tag
指定迭代器遍历 - 这意味着你只能使用迭代器来向前遍历容器,并且一次只能踩一个元素。