
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; }