Thursday, April 10, 2008

C++ array size determination - Part 2

In my last post I showed how to create a template function to determine the size of a C++ array and promised to show how to create a template that will work with a type instead of a variable.

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>
struct array_info
{
};
This just names a template that we will specialize for arrays, like so:
  template <typename T, size_t N>
struct array_info<T[N]>
{
typedef T type;
enum { size = 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:
  typedef int IntArray[10];
size_t s = array_info<IntArray>::size; // s == 10
Or like so:
  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; // error
Generates 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>
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>);
}
This template can then be used like so:
  equal<IntArray>(lhs.getVal(), rhs.getVal());
That is not syntax you get to use everyday.

6 comments:

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

Helpful Sir can you add some more computer related information, so that I can grow in my knowledge and understanding of the business in which you make money

WunderMom said...

Well I have just been waiting on pins and needles for a blog update from you, Mr. Heif-a-ner. It's been agony. I can't wait to read the next edition. When, oh when will you return to this blog? :-)

Carl said...

I'm probably missing something here, but I'll ask anyway. The templates would be instantiated only for arrays whose sizes are known at compile time.

If you're passing around references to arrays, you already know how big the array is, so when would you need to find out how big it is using code?

In addition, given that new and delete use a cookie in memory to keep track of how the bytes allocated, is there a way to use that cookie (on a valid pointer, of course) to determine the size of any array - whether it was allocated on the stack or the heap?

Kevin Heifner said...

Carl,

The templates allow you not to have to keep track of the size or modify multiple locations in code when the size of the array changes.

I know of no portable way to get access to the size of a dynamic array.

Anonymous said...

Heifner can you please continue to update your posts? I love to learn about computers and the perspectives you embrace amaze me.