
On 6/25/06 1:59 PM, "Matt Calabrese" <rivorus@gmail.com> wrote:
On 6/25/06, me22 <me22.ca@gmail.com> wrote:
I think it's worth including. It's not all that uncommon; even Freenode/##C++'s channel bot has the following factoid: Don't use sizeof() to get the size of an array, because sizeof() will do the wrong thing if that 'array' is actually a pointer. Use the following instead: template <typename T, size_t N> size_t array_size(T (&)[N]) { return N; }
The downside of that is that it doesn't yield a compile-time constant, so you can't use it, for instance, as the size of another non-dynamically allocated array, nor for template metaprogramming, etc. For my projects, I do something like:
#include <cstddef>
namespace boost { template< typename Type, ::std::size_t Size > char (&array_size_impl( Type (&)[Size] ))[Size]; }
#define BOOST_ARRAY_SIZE( array ) sizeof( ::boost::array_size_impl( array ) )
////////////////////////
The benefit of the above is that in addition to giving an easy-to-read compile-time an error when attempting to pass a pointer, it also yields a compile-time constant value.
In what I've read in this thread, I've never seen how to get the total count of elements in a multi-dimensional array. (I just seen how to get the count of a particular dimension.) How about something like: //======================================================================== template < typename T > struct array_element_count; template < typename T, std::size_t N > struct array_element_count< T[N] >; template < typename T > struct array_element_count { BOOST_STATIC_CONSTANT( std::size_t, count = 1u ); }; template < typename T, std::size_t N > struct array_element_count< T[N] > { BOOST_STATIC_CONSTANT( std::size_t, count = N * array_element_count<T>::count ); }; //======================================================================== Of course, this counts any non-array type as having an element count of 1. This may be handy in some circumstances, since the standard lets us treat a non-array object as an array of one element to allow iteration from "&x" to "&x + 1" to work. However, it seems the people here would prefer to make that case fail. (They want array-to-pointer conversions to fail an element count, and not count the pointer as itself.) What about: //======================================================================== template < typename T > struct array_element_count; template < typename T, std::size_t N > struct array_element_count< T[N] >; template < typename T > struct array_element_count { // Nothing here so non-array instantiations fail }; template < typename T, std::size_t N > struct array_element_count< T[N] > { private: template < typename U > struct array_element_count_impl; template < typename U, std::size_t M > struct array_element_count_impl< U[M] >; template < typename U > struct array_element_count_impl { BOOST_STATIC_CONSTANT( std::size_t, count = 1u ); }; template < typename U, std::size_t M > struct array_element_count_impl< U[M] > { BOOST_STATIC_CONSTANT( std::size_t, count = M * array_element_count_impl<U>::count ); }; public: BOOST_STATIC_CONSTANT( std::size_t, count = array_element_count_impl<T>::count ); }; //======================================================================== We do have to be careful of template instantiation depth. We finally add a function template wrapper to allow inductive sizing of array objects, and give errors on non-array objects, including pointers: //======================================================================== template < typename T, std::size_t N > char (&array_element_counter(T (&)[N]))[array_element_count<T[N]>::count]; #define BOOST_ARRAY_DEEP_COUNT( Array ) \ sizeof( array_element_counter((Array)) ) //======================================================================== -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com