История изменений
Исправление 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.