Chris@16: // Copyright Neil Groves 2010. Use, modification and Chris@16: // distribution is subject to the Boost Software License, Version Chris@16: // 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // Chris@16: // For more information, see http://www.boost.org/libs/range/ Chris@16: // Chris@16: #ifndef BOOST_RANGE_COMBINE_HPP Chris@16: #define BOOST_RANGE_COMBINE_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: namespace range_detail Chris@16: { Chris@16: struct void_ { typedef void_ type; }; Chris@16: } Chris@16: Chris@16: template<> struct range_iterator< ::boost::range_detail::void_ > Chris@16: { Chris@16: typedef ::boost::tuples::null_type type; Chris@16: }; Chris@16: Chris@16: namespace range_detail Chris@16: { Chris@16: inline ::boost::tuples::null_type range_begin( ::boost::range_detail::void_& ) Chris@16: { return ::boost::tuples::null_type(); } Chris@16: Chris@16: inline ::boost::tuples::null_type range_begin( const ::boost::range_detail::void_& ) Chris@16: { return ::boost::tuples::null_type(); } Chris@16: Chris@16: inline ::boost::tuples::null_type range_end( ::boost::range_detail::void_& ) Chris@16: { return ::boost::tuples::null_type(); } Chris@16: Chris@16: inline ::boost::tuples::null_type range_end( const ::boost::range_detail::void_& ) Chris@16: { return ::boost::tuples::null_type(); } Chris@16: Chris@16: template< class T > Chris@16: struct tuple_iter Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::eval_if_c< Chris@16: ::boost::is_same::value, Chris@16: ::boost::mpl::identity< ::boost::tuples::null_type >, Chris@16: ::boost::range_iterator Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template< class Rng1, class Rng2 > Chris@16: struct tuple_range Chris@16: { Chris@16: typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::eval_if_c< Chris@16: ::boost::is_same::value, Chris@16: ::boost::range_detail::void_, Chris@16: ::boost::mpl::identity Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: < Chris@16: class R1, Chris@16: class R2, Chris@16: class R3, Chris@16: class R4, Chris@16: class R5, Chris@16: class R6 Chris@16: > Chris@16: struct generate_tuple Chris@16: { Chris@16: typedef ::boost::tuples::tuple< Chris@16: BOOST_DEDUCED_TYPENAME tuple_iter::type, Chris@16: BOOST_DEDUCED_TYPENAME tuple_iter::type, Chris@16: BOOST_DEDUCED_TYPENAME tuple_iter::type, Chris@16: BOOST_DEDUCED_TYPENAME tuple_iter::type, Chris@16: BOOST_DEDUCED_TYPENAME tuple_iter::type, Chris@16: BOOST_DEDUCED_TYPENAME tuple_iter::type Chris@16: > type; Chris@16: Chris@16: static type begin( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 ) Chris@16: { Chris@16: return ::boost::tuples::make_tuple( ::boost::begin(r1), Chris@16: ::boost::begin(r2), Chris@16: ::boost::begin(r3), Chris@16: ::boost::begin(r4), Chris@16: ::boost::begin(r5), Chris@16: ::boost::begin(r6) ); Chris@16: } Chris@16: Chris@16: static type end( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 ) Chris@16: { Chris@16: return ::boost::tuples::make_tuple( ::boost::end(r1), Chris@16: ::boost::end(r2), Chris@16: ::boost::end(r3), Chris@16: ::boost::end(r4), Chris@16: ::boost::end(r5), Chris@16: ::boost::end(r6) ); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: < Chris@16: class R1, Chris@16: class R2 = void_, Chris@16: class R3 = void_, Chris@16: class R4 = void_, Chris@16: class R5 = void_, Chris@16: class R6 = void_ Chris@16: > Chris@16: struct zip_rng Chris@16: : iterator_range< Chris@16: zip_iterator< Chris@16: BOOST_DEDUCED_TYPENAME generate_tuple::type Chris@16: > Chris@16: > Chris@16: { Chris@16: private: Chris@16: typedef generate_tuple generator_t; Chris@16: typedef BOOST_DEDUCED_TYPENAME generator_t::type tuple_t; Chris@16: typedef zip_iterator zip_iter_t; Chris@16: typedef iterator_range base_t; Chris@16: Chris@16: public: Chris@16: zip_rng( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 ) Chris@16: : base_t( zip_iter_t( generator_t::begin(r1,r2,r3,r4,r5,r6) ), Chris@16: zip_iter_t( generator_t::end(r1,r2,r3,r4,r5,r6) ) ) Chris@16: { Chris@16: BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2)); Chris@16: BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r3)); Chris@16: BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r4)); Chris@16: BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r5)); Chris@16: BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r6)); Chris@16: } Chris@16: Chris@16: template< class Zip, class Rng > Chris@16: zip_rng( Zip& z, Rng& r ) Chris@16: : base_t( zip_iter_t( generator_t::begin( z, r ) ), Chris@16: zip_iter_t( generator_t::end( z, r ) ) ) Chris@16: { Chris@16: Chris@16: // @todo: tuple::begin( should be overloaded for this situation Chris@16: } Chris@16: Chris@16: struct tuple_length : ::boost::tuples::length Chris@16: { }; Chris@16: Chris@16: template< unsigned N > Chris@16: struct get Chris@16: { Chris@16: template< class Z, class R > Chris@16: static BOOST_DEDUCED_TYPENAME ::boost::tuples::element::type begin( Z& z, R& ) Chris@16: { Chris@16: return get( z.begin().get_iterator_tuple() ); Chris@16: } Chris@16: Chris@16: template< class Z, class R > Chris@16: static BOOST_DEDUCED_TYPENAME ::boost::tuples::element::type end( Z& z, R& r ) Chris@16: { Chris@16: return get( z.end().get_iterator_tuple() ); Chris@16: } Chris@16: }; Chris@16: Chris@16: }; Chris@16: Chris@16: template< class Rng1, class Rng2 > Chris@16: struct zip_range Chris@16: : iterator_range< Chris@16: zip_iterator< Chris@16: ::boost::tuples::tuple< Chris@16: BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type Chris@16: > Chris@16: > Chris@16: > Chris@16: { Chris@16: private: Chris@16: typedef zip_iterator< Chris@16: ::boost::tuples::tuple< Chris@16: BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type Chris@16: > Chris@16: > zip_iter_t; Chris@16: typedef iterator_range base_t; Chris@16: Chris@16: public: Chris@16: zip_range( Rng1& r1, Rng2& r2 ) Chris@16: : base_t( zip_iter_t( ::boost::tuples::make_tuple(::boost::begin(r1), Chris@16: ::boost::begin(r2)) ), Chris@16: zip_iter_t( ::boost::tuples::make_tuple(::boost::end(r1), Chris@16: ::boost::end(r2)) ) ) Chris@16: { Chris@16: BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2)); Chris@16: } Chris@16: }; Chris@16: Chris@16: template< class Rng1, class Rng2, class Rng3 > Chris@16: struct zip_range3 Chris@16: : iterator_range< Chris@16: zip_iterator< Chris@16: ::boost::tuples::tuple< Chris@16: BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type Chris@16: > Chris@16: > Chris@16: > Chris@16: { Chris@16: private: Chris@16: typedef zip_iterator< Chris@16: ::boost::tuples::tuple< Chris@16: BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type, Chris@16: BOOST_DEDUCED_TYPENAME ::boost::range_iterator::type Chris@16: > Chris@16: > zip_iter_t; Chris@16: typedef iterator_range base_t; Chris@16: Chris@16: public: Chris@16: zip_range3( Rng1& r1, Rng2& r2, Rng3& r3 ) Chris@16: : base_t( zip_iter_t( ::boost::tuples::make_tuple(::boost::begin(r1), Chris@16: ::boost::begin(r2), Chris@16: ::boost::begin(r3)) ), Chris@16: zip_iter_t( ::boost::tuples::make_tuple(::boost::end(r1), Chris@16: ::boost::end(r2), Chris@16: ::boost::end(r3)) ) Chris@16: ) Chris@16: { Chris@16: BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2)); Chris@16: BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r3)); Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: struct combine_tag {}; Chris@16: Chris@16: template< class Rng > Chris@16: inline zip_rng Chris@16: operator&( combine_tag, Rng& r ) Chris@16: { Chris@16: return zip_rng(r); Chris@16: } Chris@16: Chris@16: template< class Rng > Chris@16: inline iterator_range Chris@16: operator&( combine_tag, const Rng& r ) Chris@16: { Chris@16: return iterator_range(r); Chris@16: } Chris@16: Chris@16: template Chris@16: < Chris@16: class R1, Chris@16: class R2, Chris@16: class R3, Chris@16: class R4, Chris@16: class R5, Chris@16: class Rng Chris@16: > Chris@16: inline BOOST_DEDUCED_TYPENAME zip_rng::next Chris@16: operator&( const zip_rng& zip, Chris@16: Rng& r ) Chris@16: { Chris@16: return zip_rng::next( zip, r ); Chris@16: } Chris@16: Chris@16: } // namespace range_detail Chris@16: Chris@16: template< class Rng1, class Rng2 > Chris@16: inline ::boost::range_detail::zip_range combine( Rng1& r1, Rng2& r2 ) Chris@16: { Chris@16: return ::boost::range_detail::zip_range(r1, r2); Chris@16: } Chris@16: Chris@16: template< class Rng1, class Rng2 > Chris@16: inline ::boost::range_detail::zip_range combine( const Rng1& r1, Rng2& r2 ) Chris@16: { Chris@16: return ::boost::range_detail::zip_range(r1, r2); Chris@16: } Chris@16: Chris@16: template< class Rng1, class Rng2 > Chris@16: inline ::boost::range_detail::zip_range combine( Rng1& r1, const Rng2& r2 ) Chris@16: { Chris@16: return ::boost::range_detail::zip_range(r1, r2); Chris@16: } Chris@16: Chris@16: template< class Rng1, class Rng2 > Chris@16: inline ::boost::range_detail::zip_range combine( const Rng1& r1, const Rng2& r2 ) Chris@16: { Chris@16: return ::boost::range_detail::zip_range(r1, r2); Chris@16: } Chris@16: Chris@16: } // namespace boost Chris@16: Chris@16: #endif