Boost logo

Boost :

From: Roland Richter (roland_at_[hidden])
Date: 2004-05-04 09:12:53


Hartmut Kaiser wrote:

> The Latest version of the library is available at (yahoo files sections):
> http://tinyurl.com/ysbaj (72 kB) or in the Boost sandbox.

  Sandbox is out of sync (missing detail/implementation_help.hpp), so
  I tested collection_traits.zip using MSVC++ 7.0 and gcc 3.3.1 (cygwin).

> Please always state in your review, whether you think the library should be
> accepted as a Boost library!

  Definitely YES!

> - What is your evaluation of the design?
> - What is your evaluation of the implementation?

  Elegant and current state-of-the-art.

> - What is your evaluation of the documentation?

  From the docs:

   "It is worth noticing that some functionality requires partial template
    specialization, in particular, full array support does"

  It would be nice if the doc states in more detail *which* functions require
  partial template specialization.

   "(remark: this is a very small problem since one would use boost::array<>
    anyway)"

  Well, if I knew the size of the array at compile-time; which brings me to

> - What is your evaluation of the potential usefulness of the library?

  Highly useful if one often deals with container-like collections.

  What I miss is support for scoped_array<> and shared_array<>;
  I guess, however, that it is difficult or even impossible to obtain the
  number of elements of a shared_array<> - correct?

> - Did you try to use the library? With what compiler? Did you have any
> problems?

  See above.

> - Are you knowledgeable about the problem domain?

  Since other Boosters already gave more elaborate feedback on the design etc.,
  I further focused on a special aspect of collection_traits.

  My primary interest is the boost/view library (also in the sandbox).
  Since views are meant to be lightweight wrappers with a collection-like
  interface, they should work together with collection_traits - and, in
  fact, all views submitted so far pass this test (see attached file).

  I further noticed that one view (range_view) became obsolete, and
  that other views might be easier to implement now with the help of
  collection_traits.

- Roland


#include <boost/config.hpp>
#include <boost/test/minimal.hpp>

#include <boost/collection_traits.hpp>

#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>

#include <vector>
#include <deque>
#include <cmath>

#include <boost/array.hpp>
#include <boost/shared_array.hpp>

#include <boost/view/filter_view.hpp>
#include <boost/view/function_view.hpp>
#include <boost/view/permutation_view.hpp>
#include <boost/view/range_view.hpp>
#include <boost/view/transform_view.hpp>
#include <boost/view/window_view.hpp>

template<class ContainerT>
void test_container_traits_types( ContainerT c )
{
  typedef ContainerT CT;

  BOOST_STATIC_ASSERT( ( boost::is_same< boost::value_type_of<CT>::type, typename CT::value_type >::value ) );
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::iterator_of<CT>::type, typename CT::iterator >::value ) );
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::const_iterator_of<CT>::type, typename CT::const_iterator >::value ) );
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::difference_type_of<CT>::type, typename CT::difference_type >::value ) );
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::size_type_of<CT>::type, typename CT::size_type >::value ) );
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::result_iterator_of<CT>::type, typename CT::iterator >::value ) );
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::result_iterator_of<const CT>::type, typename CT::const_iterator >::value ) );
  
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::value_type_of<const CT>::type, typename CT::value_type >::value ) );
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::iterator_of<const CT>::type, typename CT::iterator >::value ) );
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::const_iterator_of<const CT>::type, typename CT::const_iterator >::value ) );
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::difference_type_of<const CT>::type, typename CT::difference_type >::value ) );
  BOOST_STATIC_ASSERT( ( boost::is_same< boost::size_type_of<const CT>::type, typename CT::size_type >::value ) );
}

template<class ContainerT>
void test_container_traits_functions( ContainerT c )
{
  BOOST_CHECK( boost::begin( c ) == c.begin() );
  BOOST_CHECK( boost::end( c ) == c.end() );
  BOOST_CHECK( boost::empty( c ) == c.empty() );
  BOOST_CHECK( boost::size( c ) == c.size() );
}

template<class ContainerT>
void test_container_traits_const_functions( ContainerT c )
{
  const ContainerT cc = c;

  BOOST_CHECK( boost::begin( cc ) == cc.begin() );
  BOOST_CHECK( boost::end( cc ) == cc.end() );
  BOOST_CHECK( boost::empty( cc ) == cc.empty() );
  BOOST_CHECK( boost::size( cc ) == cc.size() );
}

template<class ContainerT>
void test_container_traits( ContainerT c )
{
  test_container_traits_types( c );
  test_container_traits_functions( c );
  test_container_traits_const_functions( c );
}

// Skipped test_array_traits_types()
template<class ArrayT>
void test_array_functions( ArrayT a )
{
#ifndef BOOST_MSVC
  typedef boost::value_type_of<ArrayT>::type value_type;
  const int N = sizeof(a)/sizeof(value_type);

  BOOST_CHECK( boost::begin( a ) == a );
  BOOST_CHECK( boost::end( a ) == a + N );
  BOOST_CHECK( boost::empty( a ) == ( boost::size( a ) == 0 ) );
  BOOST_CHECK( boost::size( a ) == N );
#endif
}

struct linear: public std::unary_function<double,double>
{
  linear( double theK = 1., double theD = 0. )
    : k( theK ), d( theD )
  { }

  double operator()( double x ) const
    { return k*x + d; }

  double k;
  double d;
};

struct is_positive_number {
  bool operator()(int x) { return x > 0; }
};

int test_main(int, char *[])
{
  typedef int int_array[7];
  int_array a = { 0, -1, 4, -3, 5, 8, -2 };
  const int N = sizeof(a)/sizeof(int);

  //test_array_functions( a ); // Does NOT compile with gcc
  test_array_functions<int_array>( a );

  std::vector<int> v( a, a + N );
  test_container_traits( v );

  boost::array<int,7> ba = {{ 0, -1, 4, -3, 5, 8, -2 }};
  test_container_traits( ba );

  boost::shared_array<int> sa( new int[7] );
  //test_array_functions( sa ); // Wishful thinking.

  boost::view::range_view<int*, const int*> rv( a, a+7 );
  test_container_traits( rv );

  boost::view::window_view< std::vector<int> > wv( v, v.begin(), 3 );
  test_container_traits_types( wv );
  test_container_traits_functions( wv );
  //test_container_traits_const_functions( wv );

  boost::view::function_view< linear, int > lv( 0, 10, linear( 2., -3. ) );
  test_container_traits( lv );

  boost::view::filter_view< std::vector<int>, is_positive_number > fv( v );
  test_container_traits( fv );

  std::deque<int> r; // the re-indexing scheme
  for( int i = 0; i < v.size(); ++i )
    { r.push_back( (2*i) % N ); }

  boost::view::permutation_view< std::vector<int>, std::deque<int> >
    pv( v, r );
  test_container_traits( pv );

  double (*doubleAbs)(double) = fabs; // Tell VC++ 7.0 which fabs to take to prevent an internal error.
  std::pointer_to_unary_function<double,double> absf( doubleAbs );
  boost::view::transform_view< std::vector<int>,
                               std::pointer_to_unary_function<double,double> > tv( v, absf );
  test_container_traits( tv );

  return 0;
}


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