|
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