创建一个简单的前向迭代器,该迭代器将自动包装在循环缓冲区的“末端”

问题描述 投票:0回答:1

我通过继承std :: vector并重载了其operator []以使用矢量大小对所需索引取模,从而创建了一个简单的循环缓冲区:

template <typename T>
class circvector : public std::vector<T> {
public:
    T& operator[](size_t index) { return *(this->data() + index%this->size()); };       // modulo index by vector size when accessing with [] operator
};

int main()
{
    circvector<int> buffer;                         // create a circvector
    buffer.resize(10);                              // resize it
    std::iota(buffer.begin(), buffer.end(), 0);     // fill with monotonically increasing integers

    for (int i = 0; i < buffer.size() * 2; i++)
        std::cout << buffer[i] << " ";              // access elements with [] beyond the circvector size is safe
}

将正确产生输出:

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

我还想创建一个“智能”前向输入迭代器,当它经过向量中的最后一个元素时,该迭代器支持operator ++(递增)和operator *(取消引用)和自动“包装”]。与其关联的基础向量的开始。

例如,该假设的迭代器将允许在圆向量的子集上更容易地执行算法库中的某些函数(通常将迭代器作为参数),而无需添加逻辑来进行检查,然后在需要时分成两个单独的调用子集跨越circvector的end-> start wrap。

我一直在阅读有关创建自定义迭代器的内容,但是描述中的内容似乎满足了我不需要的需求,所以描述变得非常冗长。加上关于最近弃用std :: iterator的讨论,我不确定从哪里开始创建自己的迭代器,或者将其与circvector类关联。

有人可以让我开始使用最低限度的模板来运行吗?

我通过继承std :: vector并重载了其operator []以向量大小对所需索引取模,从而创建了一个简单的循环缓冲区:template

circvector:public ...

c++ iterator stdvector circular-buffer
1个回答
0
投票
template <typename T> class circvector: public std::vector<T> { public: T& operator[](size_t index_) { return *(this->data() + index_%this->size()); }; // modulo index_ by vector size when accessing with [] operator class iterator; // forward declaration iterator begin() { return circvector<T>::iterator(*this, 0); } iterator end() { return circvector<T>::iterator(*this, this->size()); } // will be same as begin() due to modulo in iterator constructor initializer list private: class iterator : public std::iterator<std::output_iterator_tag, T> { private: circvector<T>& container_; // NOTE: ORDER MATTERS! // dependency injection size_t index_{ 0 }; // NOTE: ORDER MATTERS! // state of iterator public: T& operator*() const { return container_[index_]; } // this uses the overloaded operator[] which includes modulo iterator& operator+(int N) { index_ = (index_ + N) % container_.size(); return *this; } // random increment by N iterator& operator++() { index_ = (index_ + 1) % container_.size(); return *this; } // increment with modulo iterator operator++(int) { return ++(*this); } // just calls prefix increment: operator++() bool operator!=(const iterator & right) const { return index_ != right.index_ % container_.size(); } bool operator==(const iterator & right) const { return index_ == right.index_ % container_.size(); } explicit iterator(circvector<T>& container, size_t index_ = 0) : container_(container), index_(index_ % container_.size()) {} // constructor }; };
© www.soinside.com 2019 - 2024. All rights reserved.