Using range-based for with alternative ranges
I was thinking: How hard would it be to use the range-based for syntax
for ranges other than the full begin-end range. For instance, what if
you wanted it to traverse the container backwards instead of forwards?
What I mean is that one could write something like this:
//------------------------------------------------------------------
int table[] = { 1, 3, 5, 7, 9 };
std::vector<int> v(table, std::end(table));
std::cout << "Forwards:\n";
for(int element: table) std::cout << " " << element;
for(int element: v) std::cout << " " << element;
std::cout << "\nBackwards:\n";
for(int element: reverseRange(table)) std::cout << " " << element;
for(int element: reverseRange(v)) std::cout << " " << element;
std::cout << "\n";
//------------------------------------------------------------------
In other words, we would have a reverseRange() function that returns a
wrapper object that has reverse iterators for its begin() and end()
functions.
Other applications would be to traverse only part of the range, such as:
for(int element: subrange(table, 0, 3)) std::cout << " " << element;
I haven't found any utility wrappers for this in the new standard, so
I suppose the only way is to write such wrappers oneself.
So my question is: What would be the simplest implementation for eg. the
'reverseRange()' function above?
This is the "simplest" implementation I could come up with:
//------------------------------------------------------------------
#include <iterator>
template<typename Cont_t>
struct RevRange
{
typename Cont_t::reverse_iterator b, e;
RevRange(Cont_t& c): b(c.rbegin()), e(c.rend()) {}
typename Cont_t::reverse_iterator begin() { return b; }
typename Cont_t::reverse_iterator end() { return e; }
};
template<typename Elem_t, std::size_t size>
struct RevRangeArray
{
std::reverse_iterator<Elem_t*> b, e;
RevRangeArray(Elem_t (&array)[size]): b(array+size), e(array) {}
std::reverse_iterator<Elem_t*> begin() { return b; }
std::reverse_iterator<Elem_t*> end() { return e; }
};
template<typename Container_t>
inline RevRange<Container_t> reverseRange(Container_t& c)
{ return RevRange<Container_t>(c); }
template<typename Elem_t, std::size_t size>
inline RevRangeArray<Elem_t, size> reverseRange(Elem_t (&array)[size])
{ return RevRangeArray<Elem_t, size>(array); }
//------------------------------------------------------------------
It's a bit complicated and verbose, and I was wondering if a simpler
solution could be possible (and also if this could be done with one
single class rather than having to use two).