views:

662

answers:

5
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?

A: 

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.

MSN

MSN
A: 

Well I suppose the better question is, using that function definition, why does this work?

char a[10];
array_size(a);    // returns 10

Obviously the function is useless unless I put the results somewhere, but it does give the correct result. I just don't understand what's going on that makes that work. I know that it's some trickery occurring with the function parameter, primarily this part: (&)[n]

marsol0x
+24  A: 
Johannes Schaub - litb
Thanks litb I posted the same question just minutes ago :) sorry for duplication.
AraK
I'm glad you've found answers. No worries about the dupe, you couldn't know :)
Johannes Schaub - litb
+6  A: 

Think of it this way, suppose you had a bunch of functions:

// Note that you don't need to name the array, since you don't
// actually reference the parameter at all.
size_t array_size(const int (&)[1])
{
    return 1;
}

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

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

Now when you call this, which function gets called?

int a[2];
array_size(a);

Now if you templatize the arraysize, you get:

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

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:

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

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:

const int &a[1];

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:

const int (&a)[1];

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:

size_t array_size(const int (&)[1])
Eclipse
Alex
You actually need the parentheses in both situations.
Eclipse
A: 

That makes sense. Thank you.

marsol0x