// (by Ariel Badichi) #include <boost/static_assert.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/mpl/iterator_tags.hpp> #include <boost/mpl/deref.hpp> #include <boost/mpl/transform.hpp> #include <boost/mpl/next.hpp> #include <boost/mpl/iterator_range.hpp> #include <boost/mpl/begin.hpp> #include <boost/mpl/end.hpp> #include <boost/mpl/transform_view.hpp> #include <boost/mpl/placeholders.hpp> #include <boost/mpl/vector_c.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/list_c.hpp> #include <boost/mpl/prior.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/identity.hpp> #include <boost/mpl/if.hpp> #include <boost/mpl/iterator_category.hpp> #include <boost/mpl/contains.hpp>
namespace mpl = boost::mpl; using namespace boost::mpl::placeholders;
// Seq - sequence of iterator categories template<typename Seq> struct least_refined_iterator_category : mpl::eval_if< mpl::contains<Seq, mpl::forward_iterator_tag>, mpl::identity<mpl::forward_iterator_tag>, mpl::if_< mpl::contains<Seq, mpl::bidirectional_iterator_tag>, mpl::bidirectional_iterator_tag, mpl::random_access_iterator_tag > > {};
// Seq - sequence of iterators template<typename Seq> struct iterator_category_view : mpl::transform_view< Seq, mpl::iterator_category<_> > {};
template<typename IteratorSeq?> struct zip_iterator { typedef typename least_refined_iterator_category< iterator_category_view<IteratorSeq?> >::type category;
typedef IteratorSeq? base;
typedef typename mpl::transform< IteratorSeq?, mpl::deref<_1> >::type type; };
namespace boost { namespace mpl { template<typename IteratorSeq?> struct next< ::zip_iterator<IteratorSeq?> > { typedef ::zip_iterator< typename transform< IteratorSeq?, next<_1> >::type > type; };
template<typename IteratorSeq?> struct prior< ::zip_iterator<IteratorSeq?> > { typedef ::zip_iterator< typename transform< IteratorSeq?, prior<_1> >::type > type; }; } }
// I use mpl::transform instead of mpl::transform_view written in the book.
template<typename Sequences> struct zip_view : mpl::iterator_range< zip_iterator< typename mpl::transform< Sequences, mpl::begin<_1> >::type >, zip_iterator< typename mpl::transform< Sequences, mpl::end<_1> >::type > > {};
int main() { typedef mpl::vector3_c<int, 1, 2, 3> v1; typedef mpl::vector3_c<int, 4, 5, 6> v2; typedef mpl::vector3_c<int, 7, 8, 9> v3;
typedef zip_view<mpl::vector3<v1, v2, v3> > z1; typedef mpl::begin<z1>::type first1; BOOST_STATIC_ASSERT((boost::is_same< mpl::iterator_category<first1>::type, mpl::random_access_iterator_tag >::value));
typedef mpl::list3_c<int, 6, 6, 6> l1; typedef zip_view<mpl::vector<v1, l1, v2> > z2; typedef mpl::begin<z2>::type first2; BOOST_STATIC_ASSERT((boost::is_same< mpl::iterator_category<first2>::type, mpl::forward_iterator_tag >::value)); }