From 704ce0186a6a8f7deb076a22becdc6b6ac4f1498 Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Mon, 5 Apr 2010 14:12:24 +0000 Subject: [PATCH] Boost.Range fix to the combine function that did not show as a defect on most compilers. This iteration also makes the code compatible with more compilers. [SVN r61071] --- include/boost/range/combine.hpp | 272 +++++++++++++++----------------- test/combine.cpp | 20 +-- 2 files changed, 140 insertions(+), 152 deletions(-) diff --git a/include/boost/range/combine.hpp b/include/boost/range/combine.hpp index 31a540b..8b1be00 100755 --- a/include/boost/range/combine.hpp +++ b/include/boost/range/combine.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -14,40 +15,48 @@ namespace boost { - namespace detail + namespace range_detail { struct void_ { typedef void_ type; }; } - template<> struct range_iterator + template<> struct range_iterator< ::boost::range_detail::void_ > { - typedef tuples::null_type type; + typedef ::boost::tuples::null_type type; }; - namespace detail + namespace range_detail { - inline tuples::null_type range_begin( void_& ) - { return tuples::null_type(); } + inline ::boost::tuples::null_type range_begin( ::boost::range_detail::void_& ) + { return ::boost::tuples::null_type(); } - inline tuples::null_type range_end( void_& ) - { return tuples::null_type(); } + inline ::boost::tuples::null_type range_begin( const ::boost::range_detail::void_& ) + { return ::boost::tuples::null_type(); } + + inline ::boost::tuples::null_type range_end( ::boost::range_detail::void_& ) + { return ::boost::tuples::null_type(); } + + inline ::boost::tuples::null_type range_end( const ::boost::range_detail::void_& ) + { return ::boost::tuples::null_type(); } template< class T > struct tuple_iter { - typedef typename mpl::eval_if_c< is_same::value, - mpl::identity, - range_iterator >::type - type; + typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::eval_if_c< + ::boost::is_same::value, + ::boost::mpl::identity< ::boost::tuples::null_type >, + ::boost::range_iterator + >::type type; }; template< class Rng1, class Rng2 > struct tuple_range { - typedef typename mpl::eval_if_c< is_same::value, - void_, - mpl::identity >::type - type; + typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::eval_if_c< + ::boost::is_same::value, + ::boost::range_detail::void_, + ::boost::mpl::identity + >::type type; }; template @@ -57,36 +66,37 @@ namespace boost class R3, class R4, class R5, - class R6 + class R6 > struct generate_tuple { - typedef boost::tuple< typename tuple_iter::type, - typename tuple_iter::type, - typename tuple_iter::type, - typename tuple_iter::type, - typename tuple_iter::type, - typename tuple_iter::type > - type; + typedef ::boost::tuples::tuple< + BOOST_DEDUCED_TYPENAME tuple_iter::type, + BOOST_DEDUCED_TYPENAME tuple_iter::type, + BOOST_DEDUCED_TYPENAME tuple_iter::type, + BOOST_DEDUCED_TYPENAME tuple_iter::type, + BOOST_DEDUCED_TYPENAME tuple_iter::type, + BOOST_DEDUCED_TYPENAME tuple_iter::type + > type; static type begin( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 ) { - return make_tuple( boost::begin(r1), - boost::begin(r2), - boost::begin(r3), - boost::begin(r4), - boost::begin(r5), - boost::begin(r6) ); + return ::boost::tuples::make_tuple( ::boost::begin(r1), + ::boost::begin(r2), + ::boost::begin(r3), + ::boost::begin(r4), + ::boost::begin(r5), + ::boost::begin(r6) ); } static type end( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 ) { - return make_tuple( boost::end(r1), - boost::end(r2), - boost::end(r3), - boost::end(r4), - boost::end(r5), - boost::end(r6) ); + return ::boost::tuples::make_tuple( ::boost::end(r1), + ::boost::end(r2), + ::boost::end(r3), + ::boost::end(r4), + ::boost::end(r5), + ::boost::end(r6) ); } }; @@ -101,54 +111,52 @@ namespace boost > struct zip_rng : iterator_range< - zip_iterator< typename generate_tuple::type > - > + zip_iterator< + BOOST_DEDUCED_TYPENAME generate_tuple::type + > + > { private: - typedef generate_tuple - generator; - typedef typename generator::type - tuple; - typedef zip_iterator - zip_iter; - typedef iterator_range - base; + typedef generate_tuple generator_t; + typedef BOOST_DEDUCED_TYPENAME generator_t::type tuple_t; + typedef zip_iterator zip_iter_t; + typedef iterator_range base_t; public: zip_rng( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 ) - : base( zip_iter( generator::begin(r1,r2,r3,r4,r5,r6) ), - zip_iter( generator::end(r1,r2,r3,r4,r5,r6) ) ) + : base_t( zip_iter_t( generator_t::begin(r1,r2,r3,r4,r5,r6) ), + zip_iter_t( generator_t::end(r1,r2,r3,r4,r5,r6) ) ) { - BOOST_ASSERT(boost::distance(r1) <= boost::distance(r2)); - BOOST_ASSERT(boost::distance(r1) <= boost::distance(r3)); - BOOST_ASSERT(boost::distance(r1) <= boost::distance(r4)); - BOOST_ASSERT(boost::distance(r1) <= boost::distance(r5)); - BOOST_ASSERT(boost::distance(r1) <= boost::distance(r6)); + BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2)); + BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r3)); + BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r4)); + BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r5)); + BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r6)); } template< class Zip, class Rng > zip_rng( Zip& z, Rng& r ) - : base( zip_iter( generator::begin( z, r ) ), - zip_iter( generator::end( z, r ) ) ) + : base_t( zip_iter_t( generator_t::begin( z, r ) ), + zip_iter_t( generator_t::end( z, r ) ) ) { // @todo: tuple::begin( should be overloaded for this situation } - struct tuple_length : tuples::length + struct tuple_length : ::boost::tuples::length { }; template< unsigned N > struct get { template< class Z, class R > - static typename tuples::element::type begin( Z& z, R& ) + static BOOST_DEDUCED_TYPENAME ::boost::tuples::element::type begin( Z& z, R& ) { return get( z.begin().get_iterator_tuple() ); } template< class Z, class R > - static typename tuples::element::type end( Z& z, R& r ) + static BOOST_DEDUCED_TYPENAME ::boost::tuples::element::type end( Z& z, R& r ) { return get( z.end().get_iterator_tuple() ); } @@ -157,64 +165,70 @@ namespace boost }; template< class Rng1, class Rng2 > - struct zip_range - : iterator_range< - zip_iterator< - tuple< typename range_iterator::type, - typename range_iterator::type > - > > + struct zip_range + : iterator_range< + zip_iterator< + ::boost::tuples::tuple< + BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, + BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type + > + > + > { private: - typedef zip_iterator< - tuple< typename range_iterator::type, - typename range_iterator::type > + typedef zip_iterator< + ::boost::tuples::tuple< + BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, + BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type > - zip_iter; - typedef iterator_range - base; + > zip_iter_t; + typedef iterator_range base_t; public: zip_range( Rng1& r1, Rng2& r2 ) - : base( zip_iter( make_tuple(boost::begin(r1), - boost::begin(r2)) ), - zip_iter( make_tuple(boost::end(r1), - boost::end(r2)) ) ) + : base_t( zip_iter_t( ::boost::tuples::make_tuple(::boost::begin(r1), + ::boost::begin(r2)) ), + zip_iter_t( ::boost::tuples::make_tuple(::boost::end(r1), + ::boost::end(r2)) ) ) { - BOOST_ASSERT(boost::distance(r1) <= boost::distance(r2)); + BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2)); } }; template< class Rng1, class Rng2, class Rng3 > - struct zip_range3 - : iterator_range< - zip_iterator< - tuple< typename range_iterator::type, - typename range_iterator::type, - typename range_iterator::type > - > > + struct zip_range3 + : iterator_range< + zip_iterator< + ::boost::tuples::tuple< + BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, + BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, + BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type + > + > + > { private: - typedef zip_iterator< - tuple< typename range_iterator::type, - typename range_iterator::type, - typename range_iterator::type > - > - zip_iter; - typedef iterator_range - base; + typedef zip_iterator< + ::boost::tuples::tuple< + BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, + BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, + BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type + > + > zip_iter_t; + typedef iterator_range base_t; public: zip_range3( Rng1& r1, Rng2& r2, Rng3& r3 ) - : base( zip_iter( make_tuple(boost::begin(r1), - boost::begin(r2), - boost::begin(r3)) ), - zip_iter( make_tuple(boost::end(r1), - boost::end(r2), - boost::end(r3)) ) - ) + : base_t( zip_iter_t( ::boost::tuples::make_tuple(::boost::begin(r1), + ::boost::begin(r2), + ::boost::begin(r3)) ), + zip_iter_t( ::boost::tuples::make_tuple(::boost::end(r1), + ::boost::end(r2), + ::boost::end(r3)) ) + ) { - BOOST_ASSERT(distance(r1) <= distance(r2)); - BOOST_ASSERT(distance(r1) <= distance(r3)); + BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2)); + BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r3)); } }; @@ -222,89 +236,61 @@ namespace boost struct combine_tag {}; template< class Rng > - inline zip_rng + inline zip_rng operator&( combine_tag, Rng& r ) { return zip_rng(r); } template< class Rng > - inline iterator_range + inline iterator_range operator&( combine_tag, const Rng& r ) { return iterator_range(r); } template - < - class R1, + < + class R1, class R2, class R3, class R4, class R5, class Rng > - inline typename zip_rng::next - operator&( const zip_rng& zip, + inline BOOST_DEDUCED_TYPENAME zip_rng::next + operator&( const zip_rng& zip, Rng& r ) { return zip_rng::next( zip, r ); } - // - // This one should be able to be made generic - // - // template - // < - // class R1, - // class R2 = void, - // class R3 = void, - // class R4 = void, - // class R5 = void, - // class R6 = void - // > - // inline zip_range::type - // x - // - // - /* - template< class Rng1, class Rng2, class Rng3 > - inline zip_range3 - operator&( const zip_range& r1, const Rng3& r3 ) - { - return zip_range3( - }*/ - - } // namespace 'detail' + } // namespace range_detail template< class Rng1, class Rng2 > - inline detail::zip_range combine( Rng1& r1, Rng2& r2 ) + inline ::boost::range_detail::zip_range combine( Rng1& r1, Rng2& r2 ) { - return detail::zip_range(r1,r2); + return ::boost::range_detail::zip_range(r1, r2); } template< class Rng1, class Rng2 > - inline detail::zip_range combine( const Rng1& r1, Rng2& r2 ) + inline ::boost::range_detail::zip_range combine( const Rng1& r1, Rng2& r2 ) { - return detail::zip_range(r1,r2); + return ::boost::range_detail::zip_range(r1, r2); } template< class Rng1, class Rng2 > - inline detail::zip_range combine( Rng1& r1, const Rng2& r2 ) + inline ::boost::range_detail::zip_range combine( Rng1& r1, const Rng2& r2 ) { - return detail::zip_range(r1,r2); + return ::boost::range_detail::zip_range(r1, r2); } template< class Rng1, class Rng2 > - inline detail::zip_range combine( const Rng1& r1, const Rng2& r2 ) + inline ::boost::range_detail::zip_range combine( const Rng1& r1, const Rng2& r2 ) { - return detail::zip_range(r1,r2); + return ::boost::range_detail::zip_range(r1, r2); } - // - // @todo: find a solution that scales better - // instead of adding 6 overloads! - // -} +} // namespace boost #endif diff --git a/test/combine.cpp b/test/combine.cpp index 9e29a11..c020626 100644 --- a/test/combine.cpp +++ b/test/combine.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include @@ -26,23 +26,25 @@ struct add }; template< class CombinedRng > -void apply( const CombinedRng& r ) +void apply( const CombinedRng& r ) { std::vector v; - for( typename boost::range_iterator::type - i = boost::begin(r), - e = boost::end(r); - i != e; ++i ) + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iterator_t; + + iterator_t e = boost::end(r); + for (iterator_t i = boost::begin(r); i != e; ++i) { - } } void test_combine() { std::vector v1, v2, v3; - v1 = boost::assign::list_of(1)(2)(3)(4); - v2 = boost::assign::list_of(1)(2)(3)(4); + for (int i = 1; i <= 4; ++i) + { + v1.push_back(i); + v2.push_back(i); + } int i1, i2; BOOST_FOREACH( boost::tie( i1, i2 ), boost::combine(v1,v2) )