无论如何,您要达到什么目的……您的班级是否有任何内部存储空间,还是仅代表数字序列?
如果是这样,那么问题出在运算符上T &operator*()
,T *operator->()
它们允许更改迭代器指向的值。但如果它只是范围类,它显然不能以这种方式编辑,你应该使用cons_iterator
.
如果你的类有一个内部存储,那么你的交互器应该有指向它的指针(T* pData_;
而不是T pData_;
),然后你不需要删除星号,T &operator*()
其中令人惊讶的是已经为正确的版本做好了准备;)关键是 incrementivg 迭代器应该增加这个指针并增加值在你的add1
函数中应该增加指向值。现在这两个操作都增加了同一个变量,所以你得到了那些+=2
.
编辑:
@DavidRodríguez-dribeas - 您正在考虑不同的输入迭代器类别,这些类别旨在描述允许的顺序访问(可以访问哪些序列元素)之间的区别,但所描述的问题是Range
类实例是设计常量(至少不是可以仅使用迭代器进行修改)。我看不出任何反对给予它随机访问类别的东西。
唯一的选择是在任何地方都用 const_iterator 替换迭代器,这样迭代的值就不能被修改。现在这有点违反 ISO C++,它将容器分为几个类别,并且对于它需要的每个类别,begin()
并且只有在容器本身被声明时才end()
返回。但是我认为在 ISO C++ 视图中类甚至是容器是有争议的,因为(根据 23.1.1)const_iterator
const
Range
容器是存储其他对象的对象。它们通过构造函数、析构函数、插入和擦除操作来控制这些对象的分配和释放。
在 Range 类中似乎没有任何实际的迭代对象存储,我认为我们在这里很疯狂,不需要那么遵守标准。
编辑2:
首先const iterator
是不一样的const_iterator
。第一个是无法更改的迭代器(指向序列中的不同值,例如递增),另一个允许这样做,但不允许更改指向的值,因此(*i)=3
会失败。
其次,我会这样做:
template <typename T>
class Range {
public:
class const_iterator;
typedef const_iterator iterator; //For stl-compliance - some algorythms use that.
IntegerRange(T low, T high) : low_(low), high_(high) { assert(low <= high);}
const_iterator begin() const { return const_iterator(low_); }
const_iterator end() const { return const_iterator(high_); }
private:
const T low_;
const T high_;
};
template<typename T>
class Range<T>::const_iterator : public std::iterator<std::forward_iterator_tag, T>
{
public:
// default constructor
const_iterator() : pData_(0)
{
}
// constructor from const T&
const_iterator(const T &pData) : pData_(pData)
{
}
// constructor from T&
const_iterator(T &pData) : pData_(pData)
{
}
// operator =
const_iterator &operator=(const const_iterator &other)
{
this->pData_ = other.pData_;
return *this;
}
// pre-increment operator
const_iterator & operator++()
{
++(this->pData_);
return *this;
}
// post-increment operator
const_iterator operator++(int)
{
const_iterator temp(*this);
this->operator++();
return temp;
}
// operator ==
bool operator==(const const_iterator &other) const
{
return this->pData_ == other.pData_;
}
// operator !=
bool operator!=(const iterator &other) const
{
return !operator==(other);
}
// operator* r-value
const T &operator*() const
{
return (this->pData_); // had to remove the *
}
// operator-> r-value
const T *operator->() const
{
return &(this->pData_);
}
private:
T pData_;
};
只要您遵守 const_iterator 规范,您显然可以自由地保留名称迭代器而不是 const_iterator(或使用 qqwfmnghng 作为类名) - 在这种情况下,不提供左值运算符,因为它们旨在修改指向值 - 什么这有意义吗?