Writing STL like iterator

c++, data-structures, iterator, operators, stl

Solution

I think the issue is in these lines:

    bool operator==(iterator &rhs){
        return (this->_container==rhs._container && this->_idx == rhs._idx);
    }
    bool operator!=(iterator &rhs){
        return !(*this==rhs);
    }  

The problem here is that these functions take in lvalue references to their arguments. This means that if you try passing an rvalue (for example, a temporary object returned from a function) into these operators, you will get a compile-time error because references cannot bind to temporaries. To fix this, either change the arguments to be const references:

    bool operator==(const iterator &rhs){
        return (this->_container==rhs._container && this->_idx == rhs._idx);
    }
    bool operator!=(const iterator &rhs){
        return !(*this==rhs);
    }  

Since const references can bind to temporaries, or have them take their arguments by value:

    bool operator==(iterator rhs){
        return (this->_container==rhs._container && this->_idx == rhs._idx);
    }
    bool operator!=(iterator rhs){
        return !(*this==rhs);
    }  

Whichever choice you make, you should probably mark these functions `const` because they don't mutate the receiver object.

Hope this helps!

Problem

I was trying to learn writing stl like iterators, for that I wrote a simple circular array and added an iterator in it. Please look at the bottom of the code to see the problem. ``` 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; } ``` When I compile the doesn't work part, g++ dumps the following error ``` 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] ``` the works part compiles seamlessly, when compiled without doesn't work part. Can somebody explain me what's wrong.

Original source