使用boost_foreach而不使用const_iterator
Using boost_foreach without const_iterator
是否有一种方法可以使用boost foreach而不定义const_iterator
?
我的用例是vector的迭代器,它可以包含无效元素。迭代器应该遍历vector,只产生有效的元素。它还应该修复vector,即将每个无效项与下一个有效项交换,并在最后调整vector的大小。例如,如果-1表示无效值,则向量[6,-1,-1,9,-1,2]应该迭代6,9和2,并将向量保留为[6,9,2]。
我试着用boost::iterator_facade
实现这一点,但我想不出一种方法来实现const_iterator
,因为向量可以通过删除无效值来改变,因此不能是const
。
关注点分离:容器负责其不变量,迭代器负责遍历。如果您将修复移到容器中,则可以将逻辑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();
}
所有形式的"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;
}
}
看,只是一个简单的循环。不需要花哨的迭代器外观或其他类似的噱头。