This question already has an answer here:
- Magic arguments in function templates 3 answers
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?
Think of it this way, suppose you had a bunch of functions:
Now when you call this, which function gets called?
Now if you templatize the arraysize, you get:
The compiler will attempt to instantiate a version of array_size that matches whatever parameter you call it with. So if you call it with an array of 10 ints, it will instantiate array_size with n=10.
Next, just templatize the type, so you can call it with more than just int arrays:
And you're done.
Edit: A note about the
(&)
The parentheses are needed around the
&
to differentiate between array of int references (illegal) and reference to array of ints (what you want). Since the precedence of[]
is higher than&
, if you have the declaration:because of operator precedence, you end up with a one-element array of const references to int. If you want the
&
applied first, you need to force that with parentheses:Now the you have a const reference to a one element array of ints. In the function parameter list, you don't need to specify the name of a parameter if you don't use it, so you can drop the name, but keep the parentheses:
A little weird way to get the result as compile-time const for those of us who don't have "constexpr":
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:
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
Called with our previously defined array
a
will implicitly instantiate the following function:Which can be used like this:
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
:You say if the array has
n
elements, the return type is a reference to an array having sizen
and element typechar
. Now, you can get a compile-time determined size of the passed array:Because an array of
char
havingn
elements has sizeofn
, that will give you the number of elements in the given array too. At compile time, so you can doBecause 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.
Nothing happens to the array. It's an unused parameter that is used to resolve the signature of the template function.
It also cannot be used as a template argument, but that's a separate nit.