Combining multiple for loops into single iterator

  • A+

Say I have a nest for loop like

for (int x = xstart; x < xend; x++){     for (int y = ystart; y < yend; y++){         for (int z = zstart; z < zend; z++){             function_doing_stuff(std::make_tuple(x, y, z));         }     } } 

and would like to transform it into

MyRange range(xstart,xend,ystart,yend, zstart,zend); for (auto point : range){     function_doing_stuff(point); } 

How would I write the MyRange class to be as efficient as the nested for loops? The motivation for this is to be able to use std algorithms (such as transform, accumulate, etc), and to create code that is largely dimension agnostic.

By having an iterator, it would be easy to create templated functions that operate over a range of 1d, 2d or 3d points.

Code base is currently C++14.


You can introduce your own class as

class myClass {   public:     myClass (int x, int y, int z):m_x(x) , m_y(y), m_z(z){};   private:      int m_x, m_y, m_z;  } 

and then initialize a std::vector<myClass> with you triple loop

std::vector<myClass> myVec; myVec.reserve((xend-xstart)*(yend-ystart)*(zend-zstart)); // alloc memory only once; for (int x = ystart; x < xend; x++){     for (int y = xstart; y < yend; y++){ // I assume you have a copy paste error here         for (int z = zstart; z < zend; z++){             myVec.push_back({x,y,z})         }     } } 

Finally, you can use all the nice std algorithms with the std::vector<myClass> myVec. With the syntactic sugar

using MyRange = std::vector<MyClass>; 


MyRange makeMyRange(int xstart, int xend, int ystart, int yend, int zstart,int zend) {     MyRange myVec;     // loop from above     return MyRange; } 

you can write

const MyRange range = makeMyRange(xstart, xend, ystart, yend, zstart, zend); for (auto point : range){     function_doing_stuff(point); } 

With the new move semantics this wont create unneeded copies. Please note, that the interface to this function is rather bad. Perhaps rather use 3 pairs of int, denoting the x,y,z interval.

Perhaps you change the names to something meaningful.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: