|
Boost : |
From: Daniel Frey (daniel.frey_at_[hidden])
Date: 2002-06-26 03:17:08
Daniel Frey wrote:
>
> Dietmar Kuehl wrote:
> >
> > On Monday 24 June 2002 13:48, Daniel Frey wrote:
> > > I noticed that boost doesn't have any helper for sizeof_array.
> >
> > One of the very first submissions to Boost was my "array.h" header which
> > hasn't made it from the beta directory into the approved library part yet: It
> > also contains obviously useful function 'begin()' and 'end()' for the obvious
> > propose.
>
> Time to look at it again? Maybe we can merge the best of it into a new
> header/library. What I noticed about your array_traits.h are three
> things:
>
> Before we start implementing anything, we should agree on the objectives
> of such a library. I'd prefer not to mix STL-stuff with the "old"
> arrays. Other opinions?
Seems there are not many opinions. I made a list of objectives for
myself:
a) Provide safe array operations for common tasks
b) Provide glue code to ease integration with the STL
What I don't need is a class that treates arrays the same as containers.
My rationale is, that this would create a new style of using containers
which is IMHO not a good idea and that it might/will lead to some
difficulties that contradict the objectives a) and b). Another rational
is: Scott Meyers, Effective STL, Item 2: Beware the illusion of
container-independent code :)
Given that, I rearranged the code a bit to remove the clash for
boost::array and I added new 'at'-like functions to implement checked
array access. The new header and a sample test program should be
attached to this posting.
Regards, Daniel
-- Daniel Frey aixigo AG - financial training, research and technology Schloß-Rahe-Straße 15, 52072 Aachen, Germany fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99 eMail: daniel.frey_at_[hidden], web: http://www.aixigo.de
#if !defined( BOOST_ARRAY_TRAITS_HPP )
#define BOOST_ARRAY_TRAITS_HPP
#include <cstddef>
#include <stdexcept>
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
namespace boost
{
template< typename T > class array_traits
{
private:
BOOST_STATIC_ASSERT( ::boost::is_array< T >::value );
public:
typedef typename remove_bounds< T >::type value_type;
typedef typename add_pointer< value_type >::type iterator;
typedef typename add_reference< value_type >::type reference;
BOOST_STATIC_CONSTANT( std::size_t, size = sizeof( T ) / sizeof( value_type ) );
};
// Safe sizeof for arrays
template< typename T >
std::size_t
inline array_size( T& )
{
return ::boost::array_traits< T >::size;
}
// Work-around for missing 'typeof'
template< typename T, std::size_t N >
const char ( &array_to_sizeof( T(&)[N] ) )[N];
template< typename T, std::size_t N >
const char ( &array_to_sizeof( const T(&)[N] ) )[N];
template< typename T, std::size_t N >
const char ( &array_to_sizeof( volatile T(&)[N] ) )[N];
template< typename T, std::size_t N >
const char ( &array_to_sizeof( const volatile T(&)[N] ) )[N];
// Compile-time version of protected element access
template< std::size_t N, typename T >
typename array_traits< T >::reference
inline array_at( T& array )
{
BOOST_STATIC_ASSERT( N < ::boost::array_traits< T >::size );
return array[ N ];
}
// Runtime version of protected element access
template< typename T >
typename array_traits< T >::reference
inline array_at( T& array, std::size_t N )
{
if( N >= array_size( array ) ) {
// To do: Create message with values from N
// and array_size() for a better error description
throw std::range_error( "boost::array_at() range error" );
}
return array[ N ];
}
// Glue code for using arrays in the STL
template< typename T >
typename array_traits< T >::iterator
inline array_begin( T& array )
{
return array;
}
template< typename T >
typename array_traits< T >::iterator
inline array_end( T& array )
{
return array + array_size( array );
}
}
#endif // !defined( BOOST_ARRAY_TRAITS_HPP )
#include <iostream>
#include <algorithm>
#include <vector>
#include "array_traits.hpp"
int main()
{
// The basic tests
char s1[]= "Hello, world!";
std::cout << boost::array_size( s1 ) << std::endl;
const int s2[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
std::cout << boost::array_size( s2 ) << std::endl;
volatile long s3[][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 9, 10 } };
std::cout << boost::array_size( s3 ) << std::endl;
for( size_t i = 0; i < boost::array_size( s3 ); ++i ) {
for( size_t j = 0; j < boost::array_size( s3[i] ); ++j ) {
std::cout << s3[i][j] << " ";
}
}
std::cout << std::endl;
const volatile double s4[20] = {};
std::cout << boost::array_size( s4 ) << std::endl;
unsigned short s5[21][2] = {};
std::cout << boost::array_size( s5 ) << std::endl;
// Static tests
typedef double A[23];
const double s6[] = { 12.34, 23.45, 34.56 };
enum {
// An easy one
X = boost::array_traits< A >::size,
// Currently, only this works
Y = sizeof( boost::array_to_sizeof( s6 ) ),
// Given the keyword 'typeof', you should use:
// ( Note: GCC needs '__typeof' instead of 'typeof' )
Z = boost::array_traits< __typeof( s6 ) >::size
};
std::cout << X << " " << Y << " " << Z << std::endl;
// Test the glue for STL algorithms
std::ostream_iterator< const double > ois( std::cout, " " );
std::copy( boost::array_begin( s6 ), boost::array_end( s6 ), ois );
std::cout << std::endl;
std::vector< double > v1( boost::array_begin( s6 ), boost::array_end( s6 ) );
std::cout << v1.size() << std::endl;
// Safety stuff
try {
// Classic (non-protected) array access
std::cout << s6[ 2 ] << std::endl;
// Compile-time protected array access
std::cout << boost::array_at< 2 >( s6 ) << std::endl;
// Runtime protected array access
std::cout << boost::array_at( s6, 2 ) << std::endl;
// See how it fails... :)
for( int i = 0; i < 5; ++i )
std::cout << boost::array_at( s6, i ) << std::endl;
}
catch( std::runtime_error& e ) {
std::cout << "Caught exception: " << e.what() << std::endl;
}
// Tests that prevent compilation:
// Common error #1
// const char* e1 = "This won't work!";
// std::cout << boost::array_size( e1 ) << std::endl;
// Common error #2
// int* e2 = new int[42];
// std::cout << boost::array_size( e2 ) << std::endl;
// delete[] e2;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk