ぼやきごと/2013-12-26/C++:配列の要素数省略によるコンパイル時記述漏れチェック のバックアップ差分(No.1)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
#blog2navi()
*C++:配列の要素数省略によるコンパイル時記述漏れチェック [#e5f73efd]

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

#code(c,nomenu,nonumber,nooutline,noliteral,nocomment){{
constexpr int values[] = { 1, 2, 3, 4, 5 }; // 要素数は 5 になる。
}}

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

#code(c,nomenu,nonumber,nooutline,noliteral,nocomment){{
// 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!");
}}

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

固定長配列の要素数を得る @code{constexpr}; 関数を定義しておくと尚良いでしょう。((2013年12月時点のVC++ではコンパイルできません。))

#code(c,nomenu,nonumber,nooutline,noliteral,nocomment){{
#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; }
}
}}

#code(c,nomenu,nonumber,nooutline,noliteral,nocomment){{
constexpr int values[] = { 1, 2, 3, 4, 5 };
static_assert(util::array_size(values) == ReqCount, "values size error!");
}}

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

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

#code(c,nomenu,nonumber,nooutline,noliteral,nocomment){{
#include <array>

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

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

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

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

RIGHT:Category: &#x5b;[[C++>ぼやきごと/カテゴリ/C++]]&#x5d;&#x5b;[[プログラミング>ぼやきごと/カテゴリ/プログラミング]]&#x5d; - 2013-12-26 23:54:42
----
RIGHT:&blog2trackback();
#comment(above)
#blog2navi()