如果你的底层容器只是一个std::vector,那么你就知道它是一个连续的容器——这实际上让这很容易。
你可以从以下组成一个迭代器:
- 指向被迭代容器的指针(或引用),并且
- 当前迭代计数(注意:不是“索引”)。在环绕容器的
size() 之后,这将用作底层容器的 operator[] 的“索引”。
这个迭代器的行为很简单:
- 每次增量只会增加当前计数
- 每次取消引用都返回
(*elems_)[current_ % elems_->size()],这将说明“周期”的循环。
-
begin() 将简单地返回一个带有 0 计数的迭代器,并且
-
end() 将返回一个计数为elems_.size() * nperiod_ 的迭代器
LegacyForwardIterator 的示例如下:
template <typename T>
class PeriodicContainerIterator
{
public:
using value_type = T;
using reference = T&;
using pointer = T*;
using difference_type = std::ptrdiff_t;
using iterator_category = std::forward_iterator_tag;
PeriodicContainerIterator(std::vector<T>* elems, std::size_t current)
: elems_{elems},
current_{current}
{}
reference operator*() {
return (*elems_)[current_ % elems_->size()]
}
pointer operator->() {
return &(*elems_)[current_ % elems_->size()];
}
PeriodicContainerIterator& operator++() const {
++current_;
return (*this);
}
PeriodicContainerIterator operator++(int) const {
auto copy = (*this);
++current_;
return copy;
}
bool operator==(const PeriodicContainerIterator& other) const {
return current_ == other.current_;
}
bool operator!=(const PeriodicContainerIterator& other) const {
return current_ != other.current_;
}
private:
std::vector<T>* elems_;
std::size_t current_;
};
然后容器会将begin() 和end() 定义为:
PeriodicContainerIterator<Class> begin() {
return PeriodicContainerIterator<Class>{&elems_, 0};
}
PeriodicContainerIterator<Class> end() {
return PeriodicContainerIterator<Class>{&elems_, elems_->size() * nperiod_};
}
您可以轻松地将其设置为LegacyRandomAccessIterator,但这需要大量额外的函数来增加这个答案。
如果您不是特别需要它作为 迭代器,而只是想要一种简单的方法来访问周期性序列中的每个元素,那么如果您要这样做可能会更容易阅读/理解进入类似for_each 的调用,该调用需要回调。例如:
template <typename Fn>
void forEach(Fn&& fn)
{
for (auto i = 0; i < nperiod_; ++i) {
for (auto& e : elems_) {
fn(e);
}
}
}
允许使用如下:
container.forEach([&](auto& e){
// 'e' is each visited element
});