Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I write iterators for a class that is just a wrapper of a vector?

Tags:

c++

c++11

Should I write iterators for a class that is just a wrapper of a vector?

The only private member of my class called Record is a vector.

I want to be able to do this:

for (auto& elem : record) {
    // do something with elem
}

where record is of type Record. To do this I need to implement iterators for the Record class. But, I can also do this:

for (auto& elem : record.elems) {
    // do something with elem
}

where record.elems is the vector I mentioned. But this way I will need to make it public.

Another approach is:

for (auto& elem : record.getElems()) {
    // do something with elem
}

this way I get iteration, and the member stays private. Probably this is the best way to go.

My main question is, why would I bother to implement iterators for the Record class when it is just a wrapper for a vector? My colleague insists I implement iterators, and he can't even explain me why, it is just stupid.

like image 673
user3111311 Avatar asked Dec 19 '22 20:12

user3111311


2 Answers

If your class should look a range, you are best off to provide access to iterators via begin() and end() members. The key advantage is that objects of the class can be used consistent with other ranges: there isn't much doubt of how the class is meant to use and the effort is small: unless you don't expect your class to be used, you should make it as easy and obvious to use. Of course, if you don't expect you class to be used why bother writing it in the first place?

Whether these need to have a different type than those of the vector depends on whether you need to impose any constraints. If the class does 't impose constraints on the elements or on their order it is sufficient to pass on the iterators. Otherwise it may be necessary to create custom iterators.

like image 42
Dietmar Kühl Avatar answered Apr 26 '23 23:04

Dietmar Kühl


Implementing iterators will help the encapsulation of your class. If at any point in time, you decide to replace the backing vector with another data type, you might break dependencies.

Actually, you do not need to implement the iterator. You can typedef your iterators to be the vector iterators and create inline begin() and end() methods to return the vector's iterators.

EDIT: As requested a simple example:

template <class T>
class vectorWrapper
{
  typedef typename std::vector<T> backingType;
  backingType v;
public:
  typedef typename backingType::iterator iterator;
  typedef typename backingType::const_iterator const_iterator;
  iterator begin() { return v.begin(); }
  const_iterator begin() const { return v.begin(); }
  const_iterator cbegin() const { return v.cbegin(); } // C++11
  iterator end() { return v.end(); }
  const_iterator end() const { return v.end(); }
  const_iterator cend() const { return v.cend(); } // C++11
};

If needed (or wanted) reverse_iterators can be added the same way. Since the methods are likely to be inlined by the compiler, there is little to no overhead in using this.

like image 112
user1781290 Avatar answered Apr 26 '23 23:04

user1781290