使用boost_foreach而不使用const_iterator

Using boost_foreach without const_iterator

本文关键字:const iterator boost foreach 使用      更新时间:2023-10-16

是否有一种方法可以使用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;
  }
}

看,只是一个简单的循环。不需要花哨的迭代器外观或其他类似的噱头。