Home / ぼやきごと / 2013-12-26 / C++:配列の要素数省略によるコンパイル時記述漏れチェック
C++:配列の要素数省略によるコンパイル時記述漏れチェック

C++:配列の要素数省略によるコンパイル時記述漏れチェック

C++組み込みの固定長配列では、初期化リストで初期化する場合に要素数の記述を省略することができます。

constexpr int values[] = { 1, 2, 3, 4, 5 }; // 要素数は 5 になる。

この仕様の嬉しい点の1つに、ある定数値と同じ数だけ配列の要素を確保する場合に、コンパイル時アサートによる記述漏れチェックができるということが挙げられます。

// constexpr std::size_t ReqCount = 5; がどこかのヘッダで定義されているものとする。

constexpr int values[] = { 1, 2, 3, 4, 5 };
static_assert(sizeof(values) / sizeof(values[0]) == ReqCount, "values size error!");

もしどこかのヘッダで定義されている ReqCount の値が変更された場合、 static_assert によってコンパイルエラーが発生します。
これにより、「要素数の定義を変えたけど、それに依存する配列を書き換え忘れた」というミスをコンパイル時に検出することができます。

固定長配列の要素数を得る constexpr 関数を定義しておくと尚良いでしょう。*1

#include <cstddef> // for std::size_t

namespace util
{
    // 固定長配列の要素数を取得する。
    template<typename T, std::size_t N>
    constexpr std::size_t array_size(T (&)[N]) { return N; }
}
constexpr int values[] = { 1, 2, 3, 4, 5 };
static_assert(util::array_size(values) == ReqCount, "values size error!");

今回の本題はここまでです。

ところで、C++11では組み込み配列のラッパクラスとして std::array が用意されています。

#include <array>

constexpr std::array<int, 5> values = { 1, 2, 3, 4, 5 };

固定長配列を std::vector 等のコンテナと似た感じで扱える上にオーバヘッドもほぼ無い便利なクラスなのですが、こちらは要素数を必ず指定する必要があります。
上記コード中の std::array<int, 5>std::array<int> のように省略することはできません。(クラステンプレートの仕様上、当然の話ですが。)

std::array を使いつつ、組み込み配列のように要素数の変更をコンパイル時検出するには…?

これについては調査中なので次回の記事で。

Next: [C++: array クラスの要素数指定を省略し、コンパイル時に要素数チェックする]
Category: [C++][プログラミング] - 2013-12-26 23:54:42

*1 2013年12月時点のVC++ではコンパイルできません。