如何扩展 vector class 及其迭代器 C++ 的功能

How to extend the functionality of vector class as well as its iterator C++

我想找到一种干净的方法来稍微改变 std::vector 的操作方式。

问题背景

我需要能够在指针基本上向后滑动的向量中有索引,例如;如果我的向量包含 {0,1,2,3,4,5} 并且索引 [3] 需要滑动,则在遍历向量时它应该 return: 0, 1, 2, 3, 3, 4 , 5

问题

在不重写整个向量 class 并实现我的更改的情况下,是否可以将 std::vector<T> 继承到自定义 class 中,并覆盖迭代器 ++ 运算符的行为作为以及 vector::begin()? (为了记住它已经滑了一个并且不会再滑了)

我试过的

到目前为止我已经尝试了一个基本的实现,但是在尝试覆盖 begin() 函数时卡住了。

#include <vector>
#include <iostream>
#include <iterator>

template <typename T>
class myVector : public std::vector<T>{
public:
  class myIterator : public std::vector<T>::iterator
  {
    // call vector's iterotor constructor

    //override
    // iterator& operator++(void){}
    // iterator operator++(int){}
  };

  using std::vector<T>::vector; // use the constructor from vector

  // extend the begin function, but include original operation
  myVector::myIterator begin() const
  {
    std::cout << "hi\n"; // testing to see if begin has been overriden properly
    return std::vector<T>::begin();
  }

};

// print out the vector
template <typename T> 
std::ostream& operator<<(std::ostream& os, const myVector<T>& v) 
{ 
  auto begin=v.begin();
  while (begin!=v.end())
  {
    os << *begin;
    ++begin;

    if(begin!=v.end())
    {
      os << ',';
    }
  }
  return os;
} 

int main() {
  myVector<int> vec = {1,2,3,4};

  std::cout << vec << '\n';
}

如果你有其他干净的解决方案,也欢迎。

谢谢

我永远不会公开继承 std::vector。它太容易被错误使用,而且您无法控制滥用。 std::vector没有虚拟析构函数!

迭代器似乎是合适的定制点。获得一个完全兼容的迭代器还需要更多,但这对于一个工作示例来说已经足够了:

#include <iterator>
#include <vector>
#include <iostream>

template <typename It>
struct slippery_iterator {
    bool slipped = false;
    It to_be_repeated;
    It iterator;
    slippery_iterator(It iterator,It to_be_repeated) : iterator(iterator),to_be_repeated(to_be_repeated){}

    slippery_iterator& operator++(){
        if (!slipped && iterator == to_be_repeated){
            slipped = true;
            return *this;
        }        
        ++iterator;        
        return *this;
    }
    typename std::iterator_traits<It>::reference operator*(){
        return *iterator;
    }
    bool operator!=(It other) { return iterator != other;}
};

template <typename It>
slippery_iterator<It> make_slippery_iterator(It it,It slip){
    return {it,slip};
}


int main() {
    std::vector<int> x{1,2,3,4,5};
    auto begin = make_slippery_iterator(x.begin(),x.begin()+2);
    for (; begin != x.end(); ++begin){
        std::cout << *begin;
    }
}

输出:

123345

PS:请注意,我习惯于 C++11,您需要 make_x 帮助器。更新的标准不需要它。

正如其他人所说,只需定义一个自定义迭代器即可。如果你还想要漂亮的范围迭代,那么你可以定义一个自定义范围 class 返回你的自定义迭代器。

查看下面的工作示例(需要 --std=c++17):

#include <vector>
#include <iostream>

template<typename T>
class SlipIterator {
private:
  using iterator = typename std::vector<T>::const_iterator;
  iterator i;
  iterator slip;
  bool has_slipped;

public:
  SlipIterator(iterator i, iterator slip): i(i), slip(slip), has_slipped(false) {}

  SlipIterator &operator++() {
    if ((!has_slipped) && (i == slip))
      has_slipped = true;
    else
      ++i;
    return *this;
  }

  bool operator!=(SlipIterator<T> &the_end) const { return i != the_end.i; }

  const T &operator*() const { return *i; }

};

template<typename T>
class SlipperyRange {
private:
  const std::vector<T> &v;
  size_t slip_index;

public:
  SlipperyRange(const std::vector<T> &v, size_t slip_index) : v(v), slip_index(slip_index) {}

  SlipIterator<T> begin() const { return SlipIterator<T>(v.cbegin(), v.cbegin() + slip_index); }

  SlipIterator<T> end() const { return SlipIterator<T>(v.cend(), v.cend()); }
};

int main() {
  std::vector<int> v{1,2,3,4,5};
  for(const int i: SlipperyRange{v, 2})
    std::cout << i << ' ';
  std::cout << '\n';
  return 0;
}