Lets start by looking at a struct template that through specialization we can use to capture the number of elements in an array.
template <typename T>This just names a template that we will specialize for arrays, like so:
struct array_info
{
};
template <typename T, size_t N>Now we have a template that for arrays will enable us to get to the size and type of elements in the array. This can be used like so:
struct array_info<T[N]>
{
typedef T type;
enum { size = N };
};
typedef int IntArray[10];Or like so:
size_t s = array_info<IntArray>::size; // s == 10
float floatArray[array_info<IntArray>::size];If we try something other than an array we get a compiler error.
size_t s = array_info<int*>::size; // errorGenerates a compiler error similar to:
error: 'size' is not a member of '<unnamed>::array_info<int*>'This is nice, but the real power is in using this with other templates. Even though I'm working with arrays one of the apis I'm using returns a pointer instead of an array reference. I know the type (which includes its length) so I wanted to take advantage of that. Here I use the array_info in an equal method to determine the length:
template <typename A, typename T>This template can then be used like so:
bool equal(const T* lhs, const T* rhs)
{
// Use 'typename array_info<A>::type' instead of 'T' so that compiler
// verifies A and T types match up.
const typename array_info<A>::type* const end = &lhs[array_info<A>::size];
return std::equal(&lhs[0], end, rhs, &equal_to<T>);
}
equal<IntArray>(lhs.getVal(), rhs.getVal());That is not syntax you get to use everyday.