I have a container of large objects that are expensive to copy. I must sometimes iterate over the whole container normally, and sometimes in reverse. Once I determine the iteration direction, I don't need to change mid-flight, i.e. no random access needed.
I'm hoping to do something like this pattern:
#include <iostream>
#include <vector>
using namespace std;
int main( int argc, char** )
{
// pretend this is a vector of expensive objects
vector<int> foo = {1,2,3,4,5};
// calculate forward or backward iteration direction
bool backwards = (argc > 1);
if( backwards )
// prepare backward iteration, but don't copy objects
else
// prepare forward iteration, but don't copy objects
for( auto& i : /* either forward or backward */ )
{
// my loop body
cout << i;
}
return 0;
}
This is a C++11 program, but I don't think that really helps me here. I'm just not seeing the best way to do this. Thanks for any help.
Standard library containers have both normal and reverse iterators, which solves a big part of the problem.
Unfortunately, the are distinct types, so you can't create a single variable which can hold either a normal or a reverse iterator.
So what I'd do is wrap your loop in a separate function, and template it to work with both:
And then call it like this:
Of course, then you could probably just as well use one of the standard library algorithms instead of your loop:
(Note I'm using
for_each
here for simplicity. Very likely,std::transform
orstd::copy
might be better fits to describe what you want to do.I also used a lambda expression instead of the
myloop
function. You could do either, but the lambda is much shorter, and IMO easier to read.Even if this an old question I recently had the same problem and solved it this way:
Put this somewhere:
... then you can use it as simple as that:
If
reverse
is false, it will iterate over the items in normal direction. Ifreverse
is true, it will iterate backwards over the items.The C++ standard containers come with these things called "reverse iterators". Use
std::vector::rbegin()
andstd::vector::rend()
to get an iterator that iterates backwards through the vector. C++03 can do this easily:You may be able to do this, using lambdas in C++11:
Why don't you just put your algorithm into a template function? Then it's trivial to call it with begin/end or rbegin/rend.
Or you can use lambda (since it is C++11) along with
std::for_each
as:What you need is to make your own iterator wrapper. I can think of three approaches:
One that acts like like a
union
of two iterator types; it has two iterator members of different types, and a flag choosing which one is active.One that contains a single bidirectional iterator, and a flag indicating whether to operate in the forward or reverse direction.
Some sort of generic iterator thing with virtual functions. (inefficient, but probably straightforward to write)