LINUX.ORG.RU

История изменений

Исправление AntonI, (текущая версия) :

Вот такой минимальный пример:

template <typename T, int D> class Arr{
   std::vector<T> data;
   Ind<D> N, mul; // размеры и некий контекст, Ind<D> это int[D] обвешанный всякими плюшками
public:
   void init(Ind<D> N_){ 
      N = N_;  data.resize(N.prod());
      mul[0] = 1; for(int i=1; i<D; i++) mul[i] = mul[i-1]*N[i-1];
       
   }
   T& operator [](Ind<D> ijk){ return data[ijk*mul]; }

   struct iterator{
       size_t i; Ind<D> ijk;
       Arr *arr;
       T* operator -> (){ return &(arr.data[i]); }
       void operator ++(){ 
           i++; ijk[0]++; // это быстро
           if(ijk[0]==arr->N[0]) ijk = i%arr->N;  // юзаем перегруженный %, это долго
       }
       // доступ к соседям
       iterator operator + (Ind<D> delta){
           iterator ret = *this; ret.ijk += delta;
           ret.i = ret.ijk%arr->N;
           return ret;
       }
       bool is_bound_down(int axe){ return ijk[axe]==0; }
       bool is_out_down(int axe){ return ijk[axe]<0; }
       bool is_bound_up(int axe){ return ijk[axe]==arr->N[axe]-1; }
       bool is_out_up(int axe){ return ijk[axe]>=arr->N[axe]; }
   };
};

здесь состоянием является Ind ijk. Но можно к нему добавить счетчик i, где то удобнее через i, где то через ijk.

Исправление AntonI, :

Вот такой минимальный пример:

template <typename T, int D> class Arr{
   std::vector<T> data;
   Ind<D> N, mul; // размеры и некий контекст, Ind<D> это int[D] обвешанный всякими плюшками
public:
   void init(Ind<D> N_){ N = N_; mul[0] = 1; for(int i=1; i<D; i++) mul[i] = mul[i-1]*N[i-1]; }
   T& operator [](Ind<D> ijk){ return data[ijk*mul]; }

   struct iterator{
       size_t i; Ind<D> ijk;
       Arr *arr;
       T* operator -> (){ return &(arr.data[i]); }
       void operator ++(){ 
           i++; ijk[0]++; // это быстро
           if(ijk[0]==arr->N[0]) ijk = i%arr->N;  // юзаем перегруженный %, это долго
       }
       // доступ к соседям
       iterator operator + (Ind<D> delta){
           iterator ret = *this; ret.ijk += delta;
           ret.i = ret.ijk%arr->N;
           return ret;
       }
       bool is_bound_down(int axe){ return ijk[axe]==0; }
       bool is_out_down(int axe){ return ijk[axe]<0; }
       bool is_bound_up(int axe){ return ijk[axe]==arr->N[axe]-1; }
       bool is_out_up(int axe){ return ijk[axe]>=arr->N[axe]; }
   };
};

здесь состоянием является Ind ijk. Но можно к нему добавить счетчик i, где то удобнее через i, где то через ijk.

Исходная версия AntonI, :

Вот такой минимальный пример:

template <typename T, int D> class Arr{
   std::vector<T> data;
   Ind<D> N, mul; // размеры и некий контекст, Ind<D> это int[D] обвешанный всякими плюшками
public:
   void init(Ind<D> N_){ N = N_; mul[0] = 1; for(int i=1; i<D; i++) mul[i] = mul[i-1]*N[i-1]; }
   T& operator [](Ind<D> ijk){ return data[ijk*mul]; }

   struct iterator{
       size_t i; Ind<D> ijk;
       Arr *arr;
       T* operator -> (){ return &(arr.data[i]); }
       void operator ++(){ 
           i++; ijk[0]++; // это быстро
           if(ijk[0]==arr->N[0]) ijk = i%arr->N;  // юзаем перегруженный %, это долго
       }
       // доступ к соседям
       iterator operator + (Ind<D> delta){
           iterator ret = *this; ret.ijk += delta;
           ret.i = ret.ijk%arr->N;
           return ret;
       }
       bool is_bound_down(int axe){ return ijk[axe]==0; }
       bool is_out_down(int axe){ return ijk[axe]<0; }
       bool is_bound_up(int axe){ return ijk[axe]==arr->N[axe]-1; }
       bool is_out_down(int axe){ return ijk[axe]>=arr->N[axe]; }
   };
};

здесь состоянием является Ind ijk. Но можно к нему добавить счетчик i, где то удобнее через i, где то через ijk.