1D 配列 (テンプレート) として表されるグリッドであるコンテナーを設計しています。ここにコードの抜粋を投稿していますが、実際にはもっと多くのコードがあります。これは、各セルが世界の小さな領域を表すロボット アプリケーションのローリング占有グリッドとして使用されます。
私がそのグリッドで頻繁に行う操作の 1 つは、すべてのセルを調べて、それらのワールド座標も取得することです。
for( unsigned r=0; r<mygrid.rows_; ++r ) {
for( unsigned c=0; c<mygrid.cols_; ++c ) {
cell = mygrid.getRC(r,c);
mygrid.rcToXY(r,c,&x,&y);
}
}
これらすべてを格納するイテレータが必要です: セル、その rc 座標、およびその xy 座標。
for( Grid<CellType>::const_iterator it=mygrid.begin(); it!=mygrid.end(); ++it ) {
cell = *it;
printf("%d %d %f %f\n", it.r(), it.c(), it.x(), it.y());
}
オンラインの多数の回答とチュートリアルに続いて、次の実装を思いつきました。しかし、私には少し不器用に思えます。学術的な理由から、見栄えを良くしたいと考えています。また、STL互換性は素晴らしいでしょう。
template <class G, typename C>
class base_iterator
{
private:
G* grid_;
C* cell_;
unsigned r_, c_; // local
double x_, y_;
// this should be private with access for friends (Grid) only
// but I can't make it work
public:
base_iterator(G* grid, unsigned r, unsigned c) : grid_(grid), r_(r), c_(c)
{
cell_ = ( r<grid->rows_ && c<grid->cols_ ) ? &grid_->getRC(r,c) : 0;
grid_->rcToXY(r,c,&x_,&y_);
}
public:
base_iterator() : grid_(0) { }
// used to cast an iterator to a const_iterator
template <class G2, typename C2>
base_iterator(const base_iterator<G2,C2>& other)
{
grid_ = other.grid();
cell_ = & other.cell();
r_ = other.r();
c_ = other.c();
x_ = other.x();
y_ = other.y();
}
// this should be private with access for friends only
G* grid() const { return grid_; }
C& cell() { return *cell_; }
const C& cell() const { return *cell_; }
unsigned r() const { return r_; }
unsigned c() const { return c_; }
double x() const { return x_; }
double y() const { return y_; }
C* operator->() { return cell_; }
const C* operator->() const { return cell_; }
C& operator*() { return *cell_; }
const C& operator*() const { return *cell_; }
//prefix
base_iterator & operator++()
{
// my iteration logic here which needs access to grid
// in order to find the number of rows, etc.
return *this;
}
//postfix
base_iterator operator++(int)
{
base_iterator it(*this); // make a copy for result
++(*this); // Now use the prefix version to do the work
return it; // return the copy (the old) value.
}
template <class G2, typename C2>
bool operator==(const base_iterator<G2,C2> & other) const
{
return cell_ == &other.cell();
}
template <class G2, typename C2>
bool operator!=(const base_iterator<G2,C2>& other) const
{ return cell_!=other.cell(); }
};
そして、私のグリッドクラスで:
typedef base_iterator<Grid<T>,T> iterator;
typedef base_iterator<Grid<T> const, T const> const_iterator;
iterator begin() { return iterator(this,0,0); }
iterator end() { return iterator(this,rows_,cols_); }
const_iterator begin() const { return const_iterator(this,0,0); }
const_iterator end() const { return const_iterator(this,rows_,cols_); }
繰り返しますが、これは機能しますが、少しぎこちなく感じます (反復子コードのコメントを参照)。どうすれば改善できるか知りたいです。ブースト イテレータ ファサードまたはアダプタの使用に関する多数の投稿を見ましたが、それを自分のケースに適応させる方法がわかりませんでした。