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.
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.
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_iterator
s 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With