123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- // 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 <stddef.h>
- #include <boost/iterator/iterator_traits.hpp>
- #include <boost/iterator/iterator_facade.hpp>
- #include <boost/iterator/iterator_adaptor.hpp> // for enable_if_convertible
- #include <boost/iterator/iterator_categories.hpp>
- #include <boost/iterator/minimum_category.hpp>
- #include <utility> // for std::pair
- #include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
- #include <boost/type_traits/remove_reference.hpp>
- #include <boost/type_traits/remove_cv.hpp>
- #include <boost/mpl/at.hpp>
- #include <boost/mpl/fold.hpp>
- #include <boost/mpl/transform.hpp>
- #include <boost/mpl/placeholders.hpp>
- #include <boost/fusion/algorithm/iteration/for_each.hpp>
- #include <boost/fusion/algorithm/transformation/transform.hpp>
- #include <boost/fusion/sequence/convert.hpp>
- #include <boost/fusion/sequence/intrinsic/at_c.hpp>
- #include <boost/fusion/sequence/comparison/equal_to.hpp>
- #include <boost/fusion/support/tag_of_fwd.hpp>
- namespace boost {
- namespace iterators {
- // Zip iterator forward declaration for zip_iterator_base
- template<typename IteratorTuple>
- class zip_iterator;
- namespace detail
- {
- // Functors to be used with tuple algorithms
- //
- template<typename DiffType>
- class advance_iterator
- {
- public:
- advance_iterator(DiffType step) : m_step(step) {}
- template<typename Iterator>
- void operator()(Iterator& it) const
- { it += m_step; }
- private:
- DiffType m_step;
- };
- //
- struct increment_iterator
- {
- template<typename Iterator>
- void operator()(Iterator& it) const
- { ++it; }
- };
- //
- struct decrement_iterator
- {
- template<typename Iterator>
- void operator()(Iterator& it) const
- { --it; }
- };
- //
- struct dereference_iterator
- {
- template<typename>
- struct result;
- template<typename This, typename Iterator>
- struct result<This(Iterator)>
- {
- typedef typename
- remove_cv<typename remove_reference<Iterator>::type>::type
- iterator;
- typedef typename iterator_reference<iterator>::type type;
- };
- template<typename Iterator>
- typename result<dereference_iterator(Iterator)>::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<typename IteratorTuple>
- struct tuple_of_references
- : mpl::transform<
- IteratorTuple,
- iterator_reference<mpl::_1>
- >
- {
- };
- // Specialization for std::pair
- template<typename Iterator1, typename Iterator2>
- struct tuple_of_references<std::pair<Iterator1, Iterator2> >
- {
- typedef std::pair<
- typename iterator_reference<Iterator1>::type
- , typename iterator_reference<Iterator2>::type
- > type;
- };
- // Metafunction to obtain the minimal traversal tag in a tuple
- // of iterators.
- //
- template<typename IteratorTuple>
- struct minimum_traversal_category_in_iterator_tuple
- {
- typedef typename mpl::transform<
- IteratorTuple
- , pure_traversal_tag<iterator_traversal<> >
- >::type tuple_of_traversal_tags;
- typedef typename mpl::fold<
- tuple_of_traversal_tags
- , random_access_traversal_tag
- , minimum_category<>
- >::type type;
- };
- template<typename Iterator1, typename Iterator2>
- struct minimum_traversal_category_in_iterator_tuple<std::pair<Iterator1, Iterator2> >
- {
- typedef typename pure_traversal_tag<
- typename iterator_traversal<Iterator1>::type
- >::type iterator1_traversal;
- typedef typename pure_traversal_tag<
- typename iterator_traversal<Iterator2>::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<typename IteratorTuple>
- 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<IteratorTuple>::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<IteratorTuple, 0>::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<IteratorTuple>,
- value_type,
- traversal_category,
- reference,
- difference_type
- > type;
- };
- template <>
- struct zip_iterator_base<int>
- {
- typedef int type;
- };
- template <typename reference>
- struct converter
- {
- template <typename Seq>
- static reference call(Seq seq)
- {
- typedef typename fusion::traits::tag_of<reference>::type tag;
- return fusion::convert<tag>(seq);
- }
- };
- template <typename Reference1, typename Reference2>
- struct converter<std::pair<Reference1, Reference2> >
- {
- typedef std::pair<Reference1, Reference2> reference;
- template <typename Seq>
- static reference call(Seq seq)
- {
- return reference(
- fusion::at_c<0>(seq)
- , fusion::at_c<1>(seq));
- }
- };
- }
- /////////////////////////////////////////////////////////////////////
- //
- // zip_iterator class definition
- //
- template<typename IteratorTuple>
- class zip_iterator :
- public detail::zip_iterator_base<IteratorTuple>::type
- {
- // Typedef super_t as our base class.
- typedef typename
- detail::zip_iterator_base<IteratorTuple>::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<typename OtherIteratorTuple>
- zip_iterator(
- const zip_iterator<OtherIteratorTuple>& 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<reference> 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<typename OtherIteratorTuple>
- bool equal(const zip_iterator<OtherIteratorTuple>& 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<BOOST_DEDUCED_TYPENAME super_t::difference_type>(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 OtherIteratorTuple>
- typename super_t::difference_type distance_to(
- const zip_iterator<OtherIteratorTuple>& 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<typename IteratorTuple>
- inline zip_iterator<IteratorTuple>
- make_zip_iterator(IteratorTuple t)
- { return zip_iterator<IteratorTuple>(t); }
- } // namespace iterators
- using iterators::zip_iterator;
- using iterators::make_zip_iterator;
- } // namespace boost
- #endif
|