![]() |
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, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk