有没有办法在不定义const_iterator
的情况下使用boost foreach?
我的用例是一个向量的迭代器,它可以包含无效元素。迭代器应遍历向量,并仅生成有效元素。它还应该修复向量,因为它应该将每个无效项与下一个有效项交换,并在结尾处调整向量的大小。例如,如果-1表示无效值,则向量[6,-1,-1,9,-1,2]应迭代超过6,9和2,并将向量保留为[6,9,2]。
我尝试使用boost::iterator_facade
实现此功能,但我想不出实现const_iterator
的方法,因为矢量可以通过删除无效值来更改,因此不能是const
。< / p>
答案 0 :(得分:1)
关注点分离:容器负责其不变量,遍历的迭代器。如果将修复移动到容器,则可以将逻辑const
与隐藏的mutable
隐藏部分分开。
你能用“最愚蠢”的方式编写你的迭代器,将它们从容器中解开吗?例如,存储数字索引(如果它对您的容器有意义),然后调用容器的私人朋友(或更多)来访问逻辑第n个元素。
私人朋友可以在const
上重载,并且仍然可以修改mutable
部分以进行您描述的修复,然后返回该元素。
支持随机访问的容器(以及访问的数字索引)的一个(删节)示例:
template<typename T>
class vector {
mutable std::vector<std::weak_ptr<T>> data; // notice mutable
T&
fetch(int n);
T const&
fetch(int n) const; // notice const overload
public:
class const_iterator;
friend class const_iterator;
const_iterator
begin() const;
};
template<typename T>
class vector<T>::const_iterator {
int index;
vector<T> const* this_; // notice const
public:
// constructors go here
const_iterator&
operator++()
{ ++index; }
// ...
T const&
operator*() const
{ return this_->fetch(index); } // this will call the const version of fetch
};
// example implementation of the const version of fetch
template<typename T>
T const&
vector<T>::fetch(int n) const
{
auto removed = std::remove_if(data.begin(), data.end(), [](std::weak_ptr<T>& element)
{ return element.expired(); });
// mutate mutable data member in a logically const member
data.erase(data.begin(), removed);
// this assumes that there is no race condition
// bear with me for the sake of understanding the mutable keyword
return *data[n].lock();
}
答案 1 :(得分:0)
所有形式的“foreach”都专门用于迭代容器的每个元素。您不是只是迭代容器的每个元素。您在迭代时修改容器。
所以只需编写一个常规的for循环。没有必要特别聪明或任何事情。
以下是代码:
std::vector<int> it = vec.begin();
for(; it != vec.end;)
{
if(*it < 0)
{
it = vec.erase(it);
continue;
}
else
{
//Do stuff with `it`.
++it;
}
}
看,只是一个简单的循环。不需要花哨的迭代器外墙或其他类似的噱头。