Boost logo

Boost :

From: Daryle Walker (darylew_at_[hidden])
Date: 2006-07-08 19:30:13


On 6/25/06 1:59 PM, "Matt Calabrese" <rivorus_at_[hidden]> wrote:

> On 6/25/06, me22 <me22.ca_at_[hidden]> 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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk