述べたように、コードは実際には構造体ではなく、配列内の要素の数を計算します。必要に応じて、sizeof()除算を明示的に書き出すだけです。それを関数にするとしたら、その定義で配列を期待していることを明確にしたいと思います。
template<typename T,int SIZE>
inline size_t array_size(const T (&array)[SIZE])
{
return SIZE;
}
上記はxtoflに似ていますが、ポインタを渡して(つまり、動的に割り当てられた配列を指す)、誤って間違った答えを取得するのを防ぐ点が異なります。
編集:JohnMcGに従って簡略化。
編集:インライン。
残念ながら、上記はコンパイル時の答えを提供していません(コンパイラがインラインで最適化し、内部で定数になるように最適化した場合でも)。したがって、コンパイル時定数式として使用することはできません。つまり、静的配列を宣言するためのサイズとして使用することはできません。C ++ 0xでは、キーワードinlineをconstexprに置き換えると(constexprは暗黙的にインラインになります)、この問題は解消されます。
constexpr size_t array_size(const T (&array)[SIZE])
jwfearnのソリューションはコンパイル時に機能しますが、新しい名前の宣言で配列サイズを効果的に「保存」するtypedefを使用する必要があります。次に、その新しい名前を使用して定数を初期化することにより、配列サイズが計算されます。このような場合、最初から配列サイズを定数に保存するだけでもかまいません。
Martin Yorkが投稿したソリューションもコンパイル時に機能しますが、非標準のtypeof()演算子を使用する必要があります。これを回避するには、C ++ 0xを待機し、decltypeを使用します( constexprがあるため、この問題では実際には必要ありません)。もう1つの方法は、Boost.Typeofを使用することです。この場合、最終的には
#include <boost/typeof/typeof.hpp>
template<typename T>
struct ArraySize
{
private: static T x;
public: enum { size = sizeof(T)/sizeof(*x)};
};
template<typename T>
struct ArraySize<T*> {};
と書くことによって使用されます
ArraySize<BOOST_TYPEOF(foo)>::size
ここで、fooは配列の名前です。