Can someone explain this template code that gives me the size of an array?

marsol0x picture marsol0x · Jan 12, 2009 · Viewed 22.1k times · Source
template<typename T, size_t n>
size_t array_size(const T (&)[n])
{
    return n;
}

The part that I don't get is the parameters for this template function. What happens with the array when I pass it through there that gives n as the number of elements in the array?

Answer

Johannes Schaub - litb picture Johannes Schaub - litb · Jan 12, 2009

Well, first you have to understand that trying to get a value out of an array can give you a pointer to its first element:

int a[] = {1, 2, 3};
int *ap = a; // a pointer, size is lost
int (&ar)[3] = a; // a reference to the array, size is not lost

References refer to objects using their exact type or their base-class type. The key is that the template takes arrays by reference. Arrays (not references to them) as parameters do not exist in C++. If you give a parameter an array type, it will be a pointer instead. So using a reference is necessary when we want to know the size of the passed array. The size and the element type are automatically deduced, as is generally the case for function templates. The following template

template<typename T, size_t n>
size_t array_size(const T (&)[n]) {
    return n;
}

Called with our previously defined array a will implicitly instantiate the following function:

size_t array_size(const int (&)[3]) {
    return 3;
}

Which can be used like this:

size_t size_of_a = array_size(a);

There's a variation I made up some time ago [Edit: turns out someone already had that same idea here] which can determine a value at compile time. Instead of returning the value directly, it gives the template a return type depending on n:

template<typename T, size_t n>
char (& array_size(const T (&)[n]) )[n];

You say if the array has n elements, the return type is a reference to an array having size n and element type char. Now, you can get a compile-time determined size of the passed array:

size_t size_of_a = sizeof(array_size(a));

Because an array of char having n elements has sizeof n, that will give you the number of elements in the given array too. At compile time, so you can do

int havingSameSize[sizeof(array_size(a))];

Because the function never is actually called, it doesn't need to be defined, so it doesn't have a body. Hope I could clear the matter up a little bit.