#include #include #include #include #include #include #include #include template struct minimum_traversal : boost::mpl::if_, T2, T1> {}; template class product_iterator; template struct product_iterator_base { typedef boost::iterator_facade< product_iterator, boost::fusion::vector2< typename boost::range_value::type, typename boost::range_value::type >, typename minimum_traversal< typename boost::iterator_traversal::type>::type, typename boost::iterator_traversal::type>::type >::type , boost::fusion::vector2< typename boost::range_reference::type, typename boost::range_reference::type > > type; }; template class product_iterator : public product_iterator_base::type { typedef typename product_iterator_base::type base; public: product_iterator(typename boost::range_iterator::type i1, Range2& r2, typename boost::range_iterator::type i2) : iter1(i1), begin2(r2.begin()), iter2(i2), end2(r2.end()) {} template product_iterator(const product_iterator& other) : iter1(other.iter1), begin2(other.begin2), iter2(other.iter2), end2(other.end2) {} private: friend class boost::iterator_core_access; typename base::reference dereference() const { return(reference(*iter1, *iter2)); } void increment() { ++iter2; if(iter2 == end2) { iter2 = begin2; ++iter1; } } void advance(typename base::difference_type n) { typename boost::range_difference::type total = std::distance(begin2, end2); typename boost::range_difference::type remaining = std::distance(iter2, end2); if(remaining <= total % n) { iter2 = begin2; ++iter1; n -= remaining; } std::advance(iter1, n / total); std::advance(iter2, n % total); } bool equal(const product_iterator& other) const { return(iter1 == other.iter1 && iter2 == other.iter2); } typename boost::range_iterator::type iter1; typename boost::range_iterator::type begin2, iter2, end2; }; template class container_holder { public: typedef T const_type; container_holder(T& t) : impl(boost::addressof(t)) {} T& get() const { return(*impl); } private: T* impl; }; template class view_holder { public: typedef const T const_type; view_holder(T& t) : impl(t) {} T& get() { return(impl); } const T& get() const { return(impl); } private: T impl; }; template struct select_holder { typedef typename boost::mpl::if_, view_holder, container_holder >::type type; }; template class product_view { typedef typename select_holder::type r1_type; typedef typename select_holder::type r2_type; public: product_view(Range1& r1, Range2& r2) : r1(r1), r2(r2) {} typedef product_iterator iterator; typedef product_iterator const_iterator; iterator begin() { return(iterator(r1.get().begin(), r2.get(), r2.get().begin())); } iterator end() { return(iterator(r1.get().end(), r2.get(), r2.get().begin())); } const_iterator begin() const { return(iterator(r1.get().begin(), r2.get(), r2.get().begin())); } const_iterator end() const { return(iterator(r1.get().end(), r2.get(), r2.get().begin())); } private: r1_type r1; r2_type r2; }; template product_view make_product_view(Range1& r1, Range2& r2) { return(product_view(r1, r2)); } template product_view make_product_view(const Range1& r1, Range2& r2) { return(product_view(r1, r2)); } template product_view make_product_view(Range1& r1, const Range2& r2) { return(product_view(r1, r2)); } template product_view make_product_view(const Range1& r1, const Range2& r2) { return(product_view(r1, r2)); } namespace boost { namespace foreach { template struct is_lightweight_proxy > : boost::mpl::true_ {}; } } #include #include #include #include int main() { using namespace boost::assign; std::vector v1; v1 += 1, 2, 3, 4; std::vector v2; v2 += 5, 6, 7, 8; std::vector v3; v3 += 9, 10, 11, 12; typedef boost::fusion::vector2, int> element_type; BOOST_FOREACH(element_type x, make_product_view(make_product_view(v1, v2), v3)) { std::cout << x << std::endl; } }