像迭代器一样编写 STL
Writing STL like iterator
我试图学习像迭代器一样编写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]
作品部分无缝编译,当编译时没有不工作部分。有人可以解释我出了什么问题吗?
我认为问题出在这些方面:
bool operator==(iterator &rhs){
return (this->_container==rhs._container && this->_idx == rhs._idx);
}
bool operator!=(iterator &rhs){
return !(*this==rhs);
}
这里的问题是这些函数接受对其参数的左值引用。 这意味着,如果尝试将右值(例如,从函数返回的临时对象)传递给这些运算符,则会收到编译时错误,因为引用无法绑定到临时运算符。 要解决此问题,请将参数更改为常量引用:
bool operator==(const iterator &rhs){
return (this->_container==rhs._container && this->_idx == rhs._idx);
}
bool operator!=(const iterator &rhs){
return !(*this==rhs);
}
由于 const 引用可以绑定到临时引用,或者让它们按值获取参数:
bool operator==(iterator rhs){
return (this->_container==rhs._container && this->_idx == rhs._idx);
}
bool operator!=(iterator rhs){
return !(*this==rhs);
}
无论您做出哪种选择,都应该将这些函数标记为const
因为它们不会改变接收器对象。
希望这有帮助!
#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 标记 ;)
为自定义容器编写迭代器时,您可能会发现使用 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
指定迭代器遍历 - 这意味着您只能使用迭代器沿正向遍历容器,并且一次只能单步执行一个元素。
相关文章:
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 在C应用程序中运行C++(带有STL)函数
- 使用2个键的cpp-stl::优先级队列排序不正确
- 在STL容器中使用模板类
- 用C++中的CPerson(类)类型的对象初始化STL矢量
- 将stl字符串缩小到小于15个字符的容量
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 检查函数返回类型是否与STL容器类型值相同
- STL算法函数在多个一维容器上的使用
- 如何将不同的可执行文件合并到一个窗口框架中进行编码?像浏览器一样
- 在STL - C++中按成绩对学生列表进行排序?
- 为什么在C++中对链表这样做?(像堆叠一样处理它们)
- 堆栈和队列是否像C++中的数组一样传递?
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 在C 中,对Pair类STL的用途是什么,就像数据类型或容器一样
- 像迭代器一样编写 STL
- STL 容器是否像shared_ptr一样执行智能释放
- 如何像 stl 迭代器一样"invalidate"对象
- 自定义类的自定义比较器,就像STL一样