読者です 読者をやめる 読者になる 読者になる

配列の要素アクセスをコンパイル時に境界チェックする

C++

C++11のstd::arrayクラスには、std::get()という非メンバ関数が用意されています。
これは、配列の要素に、コンパイル時定数のインデックスを指定して要素アクセスするための関数です。インデックスが配列の範囲外だった場合はコンパイルエラーにしてくれます。

#include <array>

int main()
{
    std::array<int, 3> ar = {1, 2, 3};

    // OK : 1が取得される
    int& a = std::get<0>(ar);

    // コンパイルエラー! : 範囲外
//  int& b = std::get<5>(ar);
}

インデックスがコンパイル時に決定できる場合は、std::get()フリー関数を使用すれば実行時に範囲外アクセスが起こりえなくなります。積極的に使っていくといいと思います。


なお、範囲外アクセスをコンパイルエラーにしてくれるコンパイラは、VCなら2008以降、GCCは4.8以降です。
GCC 4.7段階でのlibstdc++にはstatic assertが入っていませんでした。


ちなみに、boost::arrayには1.52.0段階ではこの関数はありません。提案はされているようなので、そのうち入るでしょう。
非const左辺値参照版の実装例:

#include <iostream>
#include <boost/array.hpp>
#include <boost/static_assert.hpp>

template <std::size_t I, class T, std::size_t N>
T& get(boost::array<T, N>& ar)
{
    BOOST_STATIC_ASSERT(I < N);
    return ar[I];
}

int main()
{
    boost::array<int, 3> ar = {1, 2, 3};

    // OK : 1が取得される
    int& a = get<0>(ar);

    // コンパイルエラー! : 範囲外
//  int& b = get<5>(ar);
}