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.

C++ array size determination

My current project has me working with C-style C++ arrays. In order to make things easier and safer I created some helper templates.

Lets start with finding the the number of elements in an array. The conventional C way would be to use sizeof like:
  sizeof(array)/sizeof(array[0])
I'm not a big fan of this approach. I have seen production code by seasoned C++ developers that looks like this:
  const char* tmp = 0;
// ...
int size = sizeof(tmp)/sizeof(tmp[0]);
Of course this is sometimes hidden behind a macro:
  #define array_size(array) (sizeof(array)/sizeof(array[0]))
// ...
int size = array_size(tmp);
Either way, this gives the wrong answer. The developer, of course, is not interested in what the size of a pointer to an element divided by the size of an element is.

So, can we do better? Actually, yes, we can.
  template <typename T, size_t N>
inline
size_t array_size(const T (&lhs)[N])
{
return N;
}
Here we pass an array by reference to array_size() that extracts the size of the array and returns it. I talked briefly about array passing a few years ago.

We can now use it like so:
  int ia[10];
size_t s = array_size(ia); // s == 10
And if we try to use this with a pointer like so:
  const char* tmp = 0;
// ...
size_t s = array_size(tmp); // error
We get a compiler error similar to:
  error: no matching function for call to 'array_size(const char*&)'
Very nice.

However, sizeof can also be used with a type instead of a variable. In my next post, I'll show how we can create a template that will work with a type instead of a variable.

Wednesday, April 02, 2008

BoostCon'08

I'm speaking on Boost.Thread this year at BoostCon'08.

Here is the announcement from the Boost mailing list:

Reminder: early registration for BoostCon'08 closes Monday, April 7.
It's still not too late to avoid the late registration fee for what may
be the finest C++ event of 2008.

For the 2nd annual Boost C++ libraries conference, we've put together a
fantastic program crowned by a keynote address from Bjarne Stroustrup.
In addition to existing Boost libraries, we're covering technology of
interest to any C++ developer trying to stay on the cutting edge,
including hands-on sessions with features from the upcoming 2nd version
of the C++ standard. This year we've also added a collection of short
"author's corner" sessions for those of you who want an inside
perspective on how advanced libraries are developed. See
http://www.boostcon.com/program for details.

BoostCon 2008 will be hosted at Aspen Center for Physics, one of the
most beautiful meeting sites in the world, and a great venue for
collaboration and discovery. The combination of a relaxed pace and
intense inquiry made BoostCon'07 an event to remember, and we expect no
less for this year. Please visit http://www.boostcon.com/registration
to register.

Thanks!

-- The BoostCon Planning Committee

David Abrahams
Beman Dawes
Jeff Garland
Joel de Guzman
Eric Niebler
Sean Parent
Jeremy Siek
Matthias Troyer