如何为我的容器实现随机访问迭代器?

How can I implement random access iterators for my container?

本文关键字:随机 访问 迭代器 实现 我的      更新时间:2023-10-16

这是容器的头文件,包括尝试实现随机访问迭代器:

using namespace std;
template <class Element, class Compare = std::equal_to<Element>>
class UniqueArray {
public:
Element** data;
unsigned int curr_size;
unsigned int max_size;
int* availability_array;
explicit UniqueArray(unsigned int size);
UniqueArray(const UniqueArray& other);
~UniqueArray();
//    UniqueArray& operator=(const UniqueArray&) = delete;
unsigned int insert(const Element& element);
bool getIndex(const Element& element, unsigned int& index) const;
const Element* operator[] (const Element& element) const;
bool remove(const Element& element);
unsigned int getCount() const;
unsigned int getSize() const;
class Filter {
public:
virtual bool operator() (const Element&) const = 0;
};
UniqueArray filter(const Filter& f) const;
class UniqueArrayIsFullException{};
typedef Element ua_iterator;
typedef const Element ua_const_iterator;
ua_iterator begin(){
return **data;
}
ua_const_iterator begin() const {
return **data;
}
ua_iterator end(){
return *(*data + max_size);
}
ua_const_iterator end() const {
return *(*data + max_size);
}
};

我得到的错误摘要:

error: no match for ‘operator++’

error: no match for ‘operator*’

error: no type named ‘value_type’ in ‘struct std::iterator_traits<MtmParkingLot::Vehicle>

error: no match for ‘operator!=’

error: no match for ‘operator-’

在我的实现中,Element得到了Vehicle,所有这些缺少的运算符都引用了Vehicle

我不太确定如何处理这些错误,因为例如减去Vehicles是没有意义的。

如果希望迭代器在取消引用对象时返回对对象的引用,则必须定义一个特殊的Iterator类来执行此操作。有了boost::indirect_iterator这很简单:

#include <boost/iterator/indirect_iterator.hpp>
template <class Element, class Compare = std::equal_to<Element>>
class UniqueArray {
// ...
auto begin() {
return boost::indirect_iterator<Element**, Element>(data_);
}
auto end() {
return boost::indirect_iterator<Element**, Element>(data_ + curr_size);
}
};

简单演示


如果你想自己编码,这个想法是:

template<class Element>
class UniqueArray {
public:
//...
class Iterator {
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = Element;
using reference = Element&;
// ...
Iterator(Element** d) : data(d) { }
reference operator*() {
return **data;
}
Iterator& operator++() {
++data;
return *this;
} 
friend bool operator!=(Iterator it1, Iterator it2) {
return it1.data != it2.data;
}
// ...
private:
Element** data;        
};
Iterator begin() {
return Iterator(data);
}
Iterator end() {
return Iterator(data + curr_size);
}
};

请注意,完全随机访问迭代器需要实现许多其他成员和非成员函数。您可能希望使其成为前向迭代器以简化一些事情。

简单演示

如果你在没有类型别名的情况下编写它,你会得到这样的定义

Element begin(){
return **data;
}

并像

UniqueArray<Vehicle>::ua_iterator it = something.begin();
it++;

成为

Vehicle it = something.begin();
it++;

这使得错误的原因更加明显 - 您正在尝试将迭代器操作应用于元素类型。

如果您对迭代生成Element*感到满意,则简单的解决方案是

typedef Element** ua_iterator;
ua_iterator begin(){
return data;
}
ua_iterator end(){
return data + curr_size;
}

以及康斯特版本的类似情况。

然后你可以写

UniqueArray<Vehicle>::ua_iterator it = something.begin();
Vehicle* v = *it;

如果你想让迭代产生Element&,你需要编写一个具有适当重载和特征的迭代器类。
这不是很困难,但它变得乏味。