デフォルトコンストラクタ以外で配列を構築する
まあいくつか方法はあると思うのです。
デフォルトコンストラクタでとりあえず構築しておいて後でもう一度 init() とか呼んで初期化する2段階初期化とか、バッファだけ用意しておいて後で placement new をしてやる遅延初期化とか、もうあきらめて普通に new で構築してやるとか。
で、今回思いついたのはこんな方法。
class hoge { int v_; public: hoge(int v) : v_(v) { } }; boost::array<boost::optional<hoge>, 4> hoges; hoges[0].reset(boost::make_optional(hoge(0))); hoges[1].reset(boost::make_optional(hoge(1))); hoges[2].reset(boost::make_optional(hoge(2))); hoges[3].reset(boost::make_optional(hoge(3)));
boost::optional を使って遅延初期化してみる方法。
欠点としては、hoges の要素がほんとに入ってるの?的な状態になることと、noncopyable な hoge に対して適用できないということ。
前者はまだいいとして、後者は絶望的。
むぅぶ・せまんてぃっく先生さえいればコピーなんて発生させずに構築できるのに……。
2段階初期化は元のクラスを書き換えることになるのでありえないとして、いやまあ vector とかに入れるとかそういうことも考えるとデフォルトコンストラクタを用意する選択肢は十分にありなんだけど、自分はコンストラクタ以外で値を設定するのがあまり好きではないのでなしの方向で考えるとして、placement new でこんな感じに作るのが一番ましな選択肢なのかなと。
boost::array<byte, sizeof(hoge) * 4> hoges_buffer; new (&hoges_buffer[sizeof(hoge) * 0]) hoge(0); new (&hoges_buffer[sizeof(hoge) * 1]) hoge(1); new (&hoges_buffer[sizeof(hoge) * 2]) hoge(2); new (&hoges_buffer[sizeof(hoge) * 3]) hoge(3); boost::array<hoge, 4>& get_hoges() { return *reinterpret_cast<boost::array<hoge, 4>*>(&hoges_buffer[0]); }