// Copyright David Abrahams and Thomas Becker 2000-2006. // Copyright Kohei Takahashi 2012-2014. // // Distributed under 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) #ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_ # define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_ #include #include #include #include #include // for enable_if_convertible #include #include #include // for std::pair #include // for backward compatibility #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace iterators { // Zip iterator forward declaration for zip_iterator_base template class zip_iterator; namespace detail { // Functors to be used with tuple algorithms // template class advance_iterator { public: advance_iterator(DiffType step) : m_step(step) {} template void operator()(Iterator& it) const { it += m_step; } private: DiffType m_step; }; // struct increment_iterator { template void operator()(Iterator& it) const { ++it; } }; // struct decrement_iterator { template void operator()(Iterator& it) const { --it; } }; // struct dereference_iterator { template struct result; template struct result { typedef typename remove_reference::type>::type iterator; typedef typename iterator_reference::type type; }; template typename result::type operator()(Iterator const& it) const { return *it; } }; // Metafunction to obtain the type of the tuple whose element types // are the reference types of an iterator tuple. // template struct tuple_of_references : mpl::transform< IteratorTuple, iterator_reference > { }; // Specialization for std::pair template struct tuple_of_references > { typedef std::pair< typename iterator_reference::type , typename iterator_reference::type > type; }; // Metafunction to obtain the minimal traversal tag in a tuple // of iterators. // template struct minimum_traversal_category_in_iterator_tuple { typedef typename mpl::transform< IteratorTuple , pure_traversal_tag > >::type tuple_of_traversal_tags; typedef typename mpl::fold< tuple_of_traversal_tags , random_access_traversal_tag , minimum_category<> >::type type; }; template struct minimum_traversal_category_in_iterator_tuple > { typedef typename pure_traversal_tag< typename iterator_traversal::type >::type iterator1_traversal; typedef typename pure_traversal_tag< typename iterator_traversal::type >::type iterator2_traversal; typedef typename minimum_category< iterator1_traversal , typename minimum_category< iterator2_traversal , random_access_traversal_tag >::type >::type type; }; /////////////////////////////////////////////////////////////////// // // Class zip_iterator_base // // Builds and exposes the iterator facade type from which the zip // iterator will be derived. // template struct zip_iterator_base { private: // Reference type is the type of the tuple obtained from the // iterators' reference types. typedef typename detail::tuple_of_references::type reference; // Value type is the same as reference type. typedef reference value_type; // Difference type is the first iterator's difference type typedef typename iterator_difference< typename mpl::at_c::type >::type difference_type; // Traversal catetgory is the minimum traversal category in the // iterator tuple. typedef typename detail::minimum_traversal_category_in_iterator_tuple< IteratorTuple >::type traversal_category; public: // The iterator facade type from which the zip iterator will // be derived. typedef iterator_facade< zip_iterator, value_type, traversal_category, reference, difference_type > type; }; template <> struct zip_iterator_base { typedef int type; }; template struct converter { template static reference call(Seq seq) { typedef typename fusion::traits::tag_of::type tag; return fusion::convert(seq); } }; template struct converter > { typedef std::pair reference; template static reference call(Seq seq) { return reference( fusion::at_c<0>(seq) , fusion::at_c<1>(seq)); } }; } ///////////////////////////////////////////////////////////////////// // // zip_iterator class definition // template class zip_iterator : public detail::zip_iterator_base::type { // Typedef super_t as our base class. typedef typename detail::zip_iterator_base::type super_t; // iterator_core_access is the iterator's best friend. friend class iterator_core_access; public: // Construction // ============ // Default constructor zip_iterator() { } // Constructor from iterator tuple zip_iterator(IteratorTuple iterator_tuple) : m_iterator_tuple(iterator_tuple) { } // Copy constructor template zip_iterator( const zip_iterator& other, typename enable_if_convertible< OtherIteratorTuple, IteratorTuple >::type* = 0 ) : m_iterator_tuple(other.get_iterator_tuple()) {} // Get method for the iterator tuple. const IteratorTuple& get_iterator_tuple() const { return m_iterator_tuple; } private: // Implementation of Iterator Operations // ===================================== // Dereferencing returns a tuple built from the dereferenced // iterators in the iterator tuple. typename super_t::reference dereference() const { typedef typename super_t::reference reference; typedef detail::converter gen; return gen::call(fusion::transform( get_iterator_tuple(), detail::dereference_iterator())); } // Two zip iterators are equal if all iterators in the iterator // tuple are equal. NOTE: It should be possible to implement this // as // // return get_iterator_tuple() == other.get_iterator_tuple(); // // but equality of tuples currently (7/2003) does not compile // under several compilers. No point in bringing in a bunch // of #ifdefs here. // template bool equal(const zip_iterator& other) const { return fusion::equal_to( get_iterator_tuple(), other.get_iterator_tuple()); } // Advancing a zip iterator means to advance all iterators in the // iterator tuple. void advance(typename super_t::difference_type n) { fusion::for_each( m_iterator_tuple, detail::advance_iterator(n)); } // Incrementing a zip iterator means to increment all iterators in // the iterator tuple. void increment() { fusion::for_each( m_iterator_tuple, detail::increment_iterator()); } // Decrementing a zip iterator means to decrement all iterators in // the iterator tuple. void decrement() { fusion::for_each( m_iterator_tuple, detail::decrement_iterator()); } // Distance is calculated using the first iterator in the tuple. template typename super_t::difference_type distance_to( const zip_iterator& other ) const { return fusion::at_c<0>(other.get_iterator_tuple()) - fusion::at_c<0>(this->get_iterator_tuple()); } // Data Members // ============ // The iterator tuple. IteratorTuple m_iterator_tuple; }; // Make function for zip iterator // template inline zip_iterator make_zip_iterator(IteratorTuple t) { return zip_iterator(t); } } // namespace iterators using iterators::zip_iterator; using iterators::make_zip_iterator; } // namespace boost #endif