Inheriting std::vector::iterator for custom class?

2019-07-04 22:15发布

问题:

I am implementing a custom class that contains an STL std::vector as central data member. Now, I would like this class to provide an iterator, which merely needs to iterate through this vector and also works with C++11 range based iteration. It is very tempting to just somehow inherit the iterator from std::vector::iterator as it is supposed to do exactly the same job. Is this possible or do I need to implement a completely custom iterator?

class Custom {
private:
  std::vector<double> _data;
public:
  class iterator {
    // Want this to provide an interface to iterate through _data
    // ...
  };
  // ...
};

Custom C;
// Populate C with data ...
for (const auto& item : C) {
  // This should print the elements within _data.
  std::cout << item << std::endl;
}

回答1:

You don't need to inherit from the iterator itself. You can just provide interfaces for the iterators used by the std::vector<double>.

Here is a quick snippet:

#include <vector>
#include <iostream>

class Custom {
private:
  std::vector<double> _data;
public:
  explicit Custom(std::initializer_list<double> init) : _data(init) {}

  using iterator = std::vector<double>::iterator;
  using const_iterator = std::vector<double>::const_iterator;

  iterator begin()
  {
    return _data.begin();
  } 

  iterator end()
  {
    return _data.end();
  } 

  const_iterator cbegin() const
  {
    return _data.cbegin();
  } 

  const_iterator cend() const
  {
    return _data.cend();
  } 
};

int main()
{
  Custom C({ 1.0,2.0,3.0,4.0,5.0 });
  for (const auto &item : C)
  {
    std::cout << item << "\n";
  } 

  return 0;
}


回答2:

You can make public proxy-functions for

  • vector<T>::begin()
  • vector<T>::end()
  • vector<T>::cbegin()
  • vector<T>::cend()
  • and other vector member functions which create iterators

And iterate over your object like that:

Custom custom;

// here insert any data

for(auto it = custom.cbegin(); it != custom.cend(); ++it){
    cout << *it;
}

Also, it will work for range-based for:

for(const auto &val : custom){
     cout << val;
}