How do I create a custom class to loop over consecutive pairs of items in a STL container using a range-based loop?
This is the syntax and output I want:
<
Okay, an hour with no answers, I've come up with a solution which works. Note that this uses my own FixedLengthVector which is exactly what it sounds like.
template
class Grouped {
private:
// length of grouped objects
static const unsigned length_ = 2;
// hold pointer to base container to avoid comparing incompatible iterators
T * base_container_;
public:
// constructor
Grouped(T & base_container) :
base_container_(&base_container) {
}
// iterator
class iterator {
private:
// hold pointer to base container to avoid comparing incompatible iterators
T * base_container_;
// hold pointers to objects in base container
FixedLengthVector ptr_;
// hold iterator to last object
typename T::iterator last_iterator_;
public:
// constructor
iterator(T & base_container, typename T::iterator & it)
: base_container_(&base_container),
last_iterator_(it) {
// set up pointers if possible
unsigned i = 0;
// check for end iterator
if (last_iterator_ == base_container_->end()) {
ptr_.fill(NULL);
return;
}
// set up first object
ptr_[0] = &*last_iterator_;
// set up next objects
for (unsigned i = 1; i < length_; ++i) {
++last_iterator_;
if (last_iterator_ == base_container_->end()) {
ptr_.fill(NULL);
return;
}
ptr_[i] = &*last_iterator_;
}
}
// dereference operator
FixedLengthVector & operator * (void) {
assert(ptr_[0] != NULL);
return ptr_;
}
// pre-increment
iterator & operator ++ (void) {
// can't increase past end
assert(last_iterator_ != base_container_->end());
// find next iterator
++last_iterator_;
if (last_iterator_ == base_container_->end()) {
ptr_.fill(NULL);
return * this;
}
// cycle pointers left
for (unsigned i = 1; i < length_; ++i) {
ptr_[i - 1] = ptr_[i];
}
ptr_[length_ - 1] = &*last_iterator_;
return * this;
}
// equality comparison
bool operator == (const iterator & that) const {
return base_container_ == that.base_container_ &&
last_iterator_ == that.last_iterator_;
}
// inequality comparison
bool operator != (const iterator & that) const {
return !(*this == that);
}
};
// end iterator
iterator end() {
return iterator(*base_container_, base_container_->end());
}
// begin iterator
iterator begin() {
return iterator(*base_container_, base_container_->begin());
}
};