私は可変長データ構造、多次元イテレータを持っています:
class Iterator
{
public:
static Iterator& init(int dim, int* sizes, void* mem)
{
return *(new (mem) Iterator(dim, sizes));
}
static size_t alloc_size(int dim)
{
return sizeof(Iterator) + sizeof(int) * 2 * dim;
}
void operator++()
{
// increment counters, update pos_ and done_
}
bool done() const { return done_; }
bool pos() const { return pos_; }
private:
Iterator(int dim, int* sizes) : dim_(dim), pos_(0), done_(false)
{
for (int i=0; i<dim_; ++i) size(i) = sizes[i];
for (int i=0; i<dim_; ++i) counter(i) = 0;
}
int dim_;
int pos_;
bool done_;
int size (int i) { return reinterpret_cast<int*>(this+1)[i]; }
int& counter(int i) { return reinterpret_cast<int*>(this+1)[dim_+i]; }
};
イテレータの次元はコンパイル時には不明ですが、おそらく小さいので、次のようにイテレータにメモリを割り当てますalloca
。
void* mem = alloca(Iterator::alloc_size(dim));
for (Iterator& i = Iterator::create(dim, sizes, mem); !i.done(); ++i)
{
// do something with i.pos()
}
イテレータにメモリを割り当てるよりエレガントな方法はありますか? alloca
関数から戻ると、そのスタックが巻き戻されるため、呼び出し元のスタック フレームで使用する必要があるという事実を認識しています(例hereを参照)。この回答は、割り当てがデフォルトのパラメーターで実行されることを示唆しています。
static Iterator& init(int dim, int* sizes, void* mem = alloca(alloc_size(dim)));
どんなにエレガントでも、この解決策は役に立ちません: Default argument references parameter 'dim'
. 素敵な解決策の提案はありますか?