我正在编写一个迭代器round_robin_iter
,该迭代器会保留一堆迭代器。每当round_robin_iter
递增时,它都会以循环方式递增当前迭代器并传递到下一个迭代器。这使我可以轻松地插入不同容器中的物品。但是,随着迭代器的数量不断增加,我无法再将STL的算法与round_robin_iter
一起使用,因为在这种情况下,STL希望按值传递迭代器的价格很高。
解决这个问题的粗略想法是将reference_wrapper<rouund_robin_iter>
按值传递给STL算法,但这对我来说似乎是一个肮脏的技巧。 STL当然可以为我的问题提供一些更优雅的解决方案,不是吗?
编辑:正如HolyBlackCat所指出的,reference_wrapper
没有实现正确的接口,因此我将不得不围绕round_robin_iter
的间接编写自己的包装器...
EDIT2:根据要求,以下是迭代器的大致框架:
template<class Iter>
struct round_robin_iterator
{
using IterList = list<pair<Iter, Iter>>;
using reference = typename iterator_traits<Iter>::reference;
IterList others;
typename IterList::iterator current = others.end();
bool is_end() const { return current == others.end(); }
void operator++() {
if(!others.empty()) {
if(++(current->first) == current->second)
current = others.erase(current);
else ++current;
if(is_end()) current = others.begin();
}
}
reference operator*() { return *(current->first); }
void add_iters(const Iter& _begin, const Iter& _end) {
others.emplace_back(_begin, _end);
if(others.size() == 1) current = others.begin();
}
bool operator!=(const round_robin_iterator& rr_it) const {
if(!is_end()){
if(!rr_it.is_end()){
return current != rr_it.current;
} else return true;
} else return !rr_it.is_end();
}
};
[从非常有用的评论到问题,我收集了以下内容,用于将“大量”迭代器传递给STL算法:
std::move(iter)
)关于使用哪个容器存储迭代器的讨论,我已经使用以下基础容器在std::accumulate
和round_robin_iterators
上做了一些基准测试(以及策略,针对到达其末端的迭代器该怎么做):
std::list
(O(1)删除)std::vector
(O(n)擦除)std::deque
(O(n)擦除)std::vector
(O(n)-跳过)std::deque
(O(n)-跳过)(抱歉未在基准中包含std::tuple
版本,但我需要动态尺寸)
基准测试在(a)1个大(Z尺寸)+许多(X-1)个小(Y尺寸)范围内进行迭代,并在(b)许多(X)尺寸范围内逐渐增大(从Y到Z)进行迭代。没有副本(实际上,我删除了std::list
版本的副本构造函数+副本分配),迭代器通过move传递。可以找到代码here,但要旨如下:
std::list
在这种设置下很难被击败,即使Y接近Zstd::deque
(删除)击败std::vector
(删除)大约X> 100