web-dev-qa-db-ja.com

この「配列のサイズ」テンプレート関数はどのように機能しますか?

可能性のある複製:
誰かが私に配列のサイズを与えるこのテンプレートコードを説明できますか?
関数テンプレートのマジック引数…

誰かがこのコードの仕組みを説明できますか?このコードの目的は配列の長さを取得することであることは知っていますが、このコードの仕組みはわかりません。

template<typename T, int size>
int GetArrLength(T(&)[size]){return size;}

ありがとう。

47
BobAlmond

まず、パラメーターT(&)[size]を分析しましょう。宣言を内側から外側へ、右から左へ、括弧グループを最初に読み取ります。これは、タイプsizeのサイズTの配列への参照である名前のないパラメーターです。

つまり、任意の配列への参照を受け入れます。配列のタイプとサイズはテンプレートパラメーターです。

このように呼び出す場合:

int a[10];
GetArrLength(a);

コンパイラは、テンプレートパラメータを推測しようとします。パラメータの型を渡すものと一致させるには、Tintであり、sizeが10である必要があります(パラメータを10の配列への参照にしますints)。

次に、そのサイズを返し、配列内の要素数を取得します。


このコードには2つの「問題」があります。まず、サイズを負にすることはできません。そのため、テンプレートパラメーターと戻り値の型として符号付きの型を使用することは意味がありません。むしろ、符号なしの型を使用する必要があります。ベストはstd::size_t

template<typename T, std::size_t Size>
std::size_t GetArrLength(T(&)[Size]) { return size; }

2つ目は、配列のサイズがそうであっても、この関数の結果は定数式ではないことです。ほとんどの状況ではこれで問題ありませんが、それから定数式を取得できればより良いでしょう。それがあなたがこのソリューションで終わる場所です:

template <std::size_t N>
struct type_of_size
{
    typedef char type[N];
};

template <typename T, std::size_t Size>
typename type_of_size<Size>::type& sizeof_array_helper(T(&)[Size]);

#define sizeof_array(pArray) sizeof(sizeof_array_helper(pArray))

これは次のように使用されます。

int a[10];
const std::size_t n = sizeof_array(a); // constant-expression!

これは3つのことで機能します。1つ目は上記と同じ考え方です。テンプレートのパラメーターが入力され、配列のサイズが与えられます。

2番目の部分は、その情報を使用して特定のサイズの型を作成するため、type_of_sizeヘルパー。その部分は必ずしも必要ではありませんが、コードが読みやすくなると思います。 char[N]のサイズは常にNに等しいため、それを悪用して、配列のサイズをtype自体のサイズに「格納」することができます。

3番目の部分は、sizeofでそのサイズを取得します。実際には何も評価しないため、関数の定義は必要ありません。 「これを行うとしたら...サイズは...」というだけです。そして、サイズはchar配列にある「格納された」サイズです。

58
GManNickG