带范围检查的自制迭代器

Self made iterator with range checking

本文关键字:迭代器 范围 检查      更新时间:2023-10-16

这是我必须为学校解决的一个练习,所以请不要给我完整的解决方案,只是提示;-)

练习如下:

  • 实现一个迭代器,该迭代器封装另一个迭代器(即序列)并执行范围检查
  • 迭代器是用序列的第一个和最后一个元素初始化的
  • 如果迭代器指向第一个元素并减小,或者如果迭代者指向最后一个元素并增大,则表示错误——选择适当的错误信号形式

首先我想继承向量容器的迭代器,然后我得到了这个(只是我"解决方案"的一部分,但我意识到这很糟糕,并停止了…):

template <typename T>
class myIter : std::vector<T>::iterator
{
public:
myIter( typename std::vector<T>::iterator start,
typename std::vector<T>::iterator end,
typename std::vector<T>::iterator pos,
bool behaviour=false) : s(start), e(end), p(pos), beh(behaviour)
{overflowFlag = false;};
typename std::vector<T>::iterator & operator++();
typename std::vector<T>::iterator & operator--();
typename std::vector<T>::iterator operator++(int);
typename std::vector<T>::iterator operator--(int);
typename std::vector<T>::iterator & operator+=(int);
typename std::vector<T>::iterator & operator-=(int);
typename std::vector<T>::iterator operator+(int);
typename std::vector<T>::iterator operator-(int);
myIter & operator=(const myIter&) = delete;
T operator*(){ return *p;};
bool getFlag() {return overflowFlag;};
private:
typename std::vector<T>::iterator s, e, p;
bool beh;
bool overflowFlag; // is set if beh = false. otherwise exception;
};

所以我意识到我并没有真正继承向量迭代器(我继承了,但我没有使用它)。使用标准迭代器功能,但实现"顶部"范围检查的最简单方法是什么?如果违反了范围,我可以抛出异常或设置"errorflag"(由布尔值"beh"指定),但实现起来应该不会有问题。

我认为只存储三个迭代器(beginendcurrent)并实现特定迭代器所需的方法会容易得多,这些迭代器进行绑定检查(递增、递减),并将其他迭代器委托给包装的current迭代器。

正如您所看到的,您并没有真正使用容器类型,也没有使用它的迭代器,所以您甚至可以将迭代器类型传递给您的模板类。

template < typename T, typename Iter >
class bound_checked_iterator {
public:
bound_checked_iterator(Iter begin, Iter end)
: begin_(begin), end_(end), current_(begin) {}
// implements the different methods
bound_checked_iterator operator++();
bound_checked_iterator operator--();
bound_checked_iterator operator++(int);
bound_checked_iterator operator--(int);
T& operator *();
const T& operator *() const;
bool operator ==(bound_checked_operator const& other) const;
bool operator !=(bound_checked_operator const& other) const;
private:
Iter begin_, end_, current_;
};

迭代器需要实现的方法有:

  • 增量前后
  • 减量前后
  • 解引用运算符
  • 平等与不平等比较

您可以在此处获得完整列表。

正如@Jarod42在评论中提到的,您甚至不需要将数据类型传递给模板,但您可以使用std::iterator_traits<Iter>来推导它:

template < typename Iter >
class bound_checked_iterator {
public:
bound_checked_iterator(Iter begin, Iter end)
: begin_(begin), end_(end), current_(begin) {}
// ...
typename std::iterator_traits<Iter>::reference operator*();
// ...
};

目标是在任意迭代器类型之上添加行为。您正在编写的类将是泛型的,但它的大部分实际"迭代器性"将推迟到它的模板参数:让我们将I称为"迭代者"。

无论您在哪里使用过std::vector<T>::iterator,请改用普通I。(当你对代码进行推理时,用一个具体的类型替换I可能会有所帮助。例如,当对char[]数组进行迭代时,I将是char*。)

你的课的基本框架看起来像:

template <typename I>
class myIter
{
public:
myIter(I start, I end, I pos);
private:
I s, e, p;
};

在各种突变体(operator++--等)中,您将对照se检查p,以确保其保持在这些范围内。