How does this Array Size Template Work?
I came across this snippet
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
in this article http://software.intel.com/en-us/articles/pvs-studio-vs-chromium/
I've seen other templates to do the same thing, like this one
Use templates to get an array's size and 开发者_StackOverflowend address
and I understand those, but I've been having difficulty with this one.
Any help would be appreciated.
The function template is named ArraySizeHelper
, for a function that takes one argument, a reference to a T [N]
, and returns a reference to a char [N]
.
The macro passes your object (let's say it's X obj[M]
) as the argument. The compiler infers that T == X
and N == M
. So it declares a function with a return type of char (&)[M]
. The macro then wraps this return value with sizeof
, so it's really doing sizeof(char [M])
, which is M
.
If you give it a non-array type (e.g. a T *
), then the template parameter inference will fail.
As @Alf points out below, the advantage of this hybrid template-macro system over the alternative template-only approach is that this gives you a compile-time constant.
This isn't the nicest way of doing it, but since you're asking: The return type of the template function ArraySizeHelper
is char[N]
, where the argument of the function is a (reference to an) array of size N of type T
. Template argument deduction instantiates this template with the matching number N, and so sizeof(char[N])
is just N, which is what you get.
A nicer version could be written as follows. (You need C++0x for constexpr
; if you omit it, this will not be a constant expression.)
template <typename T, size_t N> constexpr size_t array_size(const T (&)[N]) { return N; }
Usage:
int x[20];
array_size(x); // == 20
Update: If you are in C++0x, here is another solution that gives a constexpr, thanks to decltype:
#include <type_traits>
template <typename T> struct array_traits;
template <typename T, unsigned int N> struct array_traits<T[N]>
{
static const unsigned int size = N;
typedef std::decay<T>::type type;
};
// Usage:
int x[20];
array_traits<decltype(x)>::size; // == 20
This blog on MSDN precisely describes how it works. Very interesting story. Take a look at it.
精彩评论