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