123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- // Copyright David Abrahams and Thomas Becker 2000-2006. 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.hpp>
- #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/detail/iterator.hpp>
- #include <boost/iterator/detail/minimum_category.hpp>
- #include <boost/tuple/tuple.hpp>
- #include <boost/type_traits/is_same.hpp>
- #include <boost/mpl/and.hpp>
- #include <boost/mpl/apply.hpp>
- #include <boost/mpl/eval_if.hpp>
- #include <boost/mpl/lambda.hpp>
- #include <boost/mpl/placeholders.hpp>
- #include <boost/mpl/aux_/lambda_support.hpp>
- namespace boost {
- // Zip iterator forward declaration for zip_iterator_base
- template<typename IteratorTuple>
- class zip_iterator;
- // One important design goal of the zip_iterator is to isolate all
- // functionality whose implementation relies on the current tuple
- // implementation. This goal has been achieved as follows: Inside
- // the namespace detail there is a namespace tuple_impl_specific.
- // This namespace encapsulates all functionality that is specific
- // to the current Boost tuple implementation. More precisely, the
- // namespace tuple_impl_specific provides the following tuple
- // algorithms and meta-algorithms for the current Boost tuple
- // implementation:
- //
- // tuple_meta_transform
- // tuple_meta_accumulate
- // tuple_transform
- // tuple_for_each
- //
- // If the tuple implementation changes, all that needs to be
- // replaced is the implementation of these four (meta-)algorithms.
- 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)
- { ++it; }
- };
- //
- struct decrement_iterator
- {
- template<typename Iterator>
- void operator()(Iterator& it)
- { --it; }
- };
- //
- struct dereference_iterator
- {
- template<typename Iterator>
- struct apply
- {
- typedef typename
- iterator_traits<Iterator>::reference
- type;
- };
- template<typename Iterator>
- typename apply<Iterator>::type operator()(Iterator const& it)
- { return *it; }
- };
-
- // The namespace tuple_impl_specific provides two meta-
- // algorithms and two algorithms for tuples.
- //
- namespace tuple_impl_specific
- {
- // Meta-transform algorithm for tuples
- //
- template<typename Tuple, class UnaryMetaFun>
- struct tuple_meta_transform;
-
- template<typename Tuple, class UnaryMetaFun>
- struct tuple_meta_transform_impl
- {
- typedef tuples::cons<
- typename mpl::apply1<
- typename mpl::lambda<UnaryMetaFun>::type
- , typename Tuple::head_type
- >::type
- , typename tuple_meta_transform<
- typename Tuple::tail_type
- , UnaryMetaFun
- >::type
- > type;
- };
- template<typename Tuple, class UnaryMetaFun>
- struct tuple_meta_transform
- : mpl::eval_if<
- boost::is_same<Tuple, tuples::null_type>
- , mpl::identity<tuples::null_type>
- , tuple_meta_transform_impl<Tuple, UnaryMetaFun>
- >
- {
- };
-
- // Meta-accumulate algorithm for tuples. Note: The template
- // parameter StartType corresponds to the initial value in
- // ordinary accumulation.
- //
- template<class Tuple, class BinaryMetaFun, class StartType>
- struct tuple_meta_accumulate;
-
- template<
- typename Tuple
- , class BinaryMetaFun
- , typename StartType
- >
- struct tuple_meta_accumulate_impl
- {
- typedef typename mpl::apply2<
- typename mpl::lambda<BinaryMetaFun>::type
- , typename Tuple::head_type
- , typename tuple_meta_accumulate<
- typename Tuple::tail_type
- , BinaryMetaFun
- , StartType
- >::type
- >::type type;
- };
- template<
- typename Tuple
- , class BinaryMetaFun
- , typename StartType
- >
- struct tuple_meta_accumulate
- : mpl::eval_if<
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
- mpl::or_<
- #endif
- boost::is_same<Tuple, tuples::null_type>
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
- , boost::is_same<Tuple,int>
- >
- #endif
- , mpl::identity<StartType>
- , tuple_meta_accumulate_impl<
- Tuple
- , BinaryMetaFun
- , StartType
- >
- >
- {
- };
- #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
- || ( \
- BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER) \
- )
- // Not sure why intel's partial ordering fails in this case, but I'm
- // assuming int's an MSVC bug-compatibility feature.
-
- # define BOOST_TUPLE_ALGO_DISPATCH
- # define BOOST_TUPLE_ALGO(algo) algo##_impl
- # define BOOST_TUPLE_ALGO_TERMINATOR , int
- # define BOOST_TUPLE_ALGO_RECURSE , ...
- #else
- # define BOOST_TUPLE_ALGO(algo) algo
- # define BOOST_TUPLE_ALGO_TERMINATOR
- # define BOOST_TUPLE_ALGO_RECURSE
- #endif
-
- // transform algorithm for tuples. The template parameter Fun
- // must be a unary functor which is also a unary metafunction
- // class that computes its return type based on its argument
- // type. For example:
- //
- // struct to_ptr
- // {
- // template <class Arg>
- // struct apply
- // {
- // typedef Arg* type;
- // }
- //
- // template <class Arg>
- // Arg* operator()(Arg x);
- // };
- template<typename Fun>
- tuples::null_type BOOST_TUPLE_ALGO(tuple_transform)
- (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR)
- { return tuples::null_type(); }
- template<typename Tuple, typename Fun>
- typename tuple_meta_transform<
- Tuple
- , Fun
- >::type
-
- BOOST_TUPLE_ALGO(tuple_transform)(
- const Tuple& t,
- Fun f
- BOOST_TUPLE_ALGO_RECURSE
- )
- {
- typedef typename tuple_meta_transform<
- BOOST_DEDUCED_TYPENAME Tuple::tail_type
- , Fun
- >::type transformed_tail_type;
- return tuples::cons<
- BOOST_DEDUCED_TYPENAME mpl::apply1<
- Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type
- >::type
- , transformed_tail_type
- >(
- f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f)
- );
- }
- #ifdef BOOST_TUPLE_ALGO_DISPATCH
- template<typename Tuple, typename Fun>
- typename tuple_meta_transform<
- Tuple
- , Fun
- >::type
-
- tuple_transform(
- const Tuple& t,
- Fun f
- )
- {
- return tuple_transform_impl(t, f, 1);
- }
- #endif
-
- // for_each algorithm for tuples.
- //
- template<typename Fun>
- Fun BOOST_TUPLE_ALGO(tuple_for_each)(
- tuples::null_type
- , Fun f BOOST_TUPLE_ALGO_TERMINATOR
- )
- { return f; }
-
- template<typename Tuple, typename Fun>
- Fun BOOST_TUPLE_ALGO(tuple_for_each)(
- Tuple& t
- , Fun f BOOST_TUPLE_ALGO_RECURSE)
- {
- f( t.get_head() );
- return tuple_for_each(t.get_tail(), f);
- }
-
- #ifdef BOOST_TUPLE_ALGO_DISPATCH
- template<typename Tuple, typename Fun>
- Fun
- tuple_for_each(
- Tuple& t,
- Fun f
- )
- {
- return tuple_for_each_impl(t, f, 1);
- }
- #endif
-
- // Equality of tuples. NOTE: "==" for tuples currently (7/2003)
- // has problems under some compilers, so I just do my own.
- // No point in bringing in a bunch of #ifdefs here. This is
- // going to go away with the next tuple implementation anyway.
- //
- inline bool tuple_equal(tuples::null_type, tuples::null_type)
- { return true; }
- template<typename Tuple1, typename Tuple2>
- bool tuple_equal(
- Tuple1 const& t1,
- Tuple2 const& t2
- )
- {
- return t1.get_head() == t2.get_head() &&
- tuple_equal(t1.get_tail(), t2.get_tail());
- }
- }
- //
- // end namespace tuple_impl_specific
- template<typename Iterator>
- struct iterator_reference
- {
- typedef typename iterator_traits<Iterator>::reference type;
- };
- #ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
- // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
- // out well. Instantiating the nested apply template also
- // requires instantiating iterator_traits on the
- // placeholder. Instead we just specialize it as a metafunction
- // class.
- template<>
- struct iterator_reference<mpl::_1>
- {
- template <class T>
- struct apply : iterator_reference<T> {};
- };
- #endif
-
- // 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
- : tuple_impl_specific::tuple_meta_transform<
- IteratorTuple,
- iterator_reference<mpl::_1>
- >
- {
- };
- // Metafunction to obtain the minimal traversal tag in a tuple
- // of iterators.
- //
- template<typename IteratorTuple>
- struct minimum_traversal_category_in_iterator_tuple
- {
- typedef typename tuple_impl_specific::tuple_meta_transform<
- IteratorTuple
- , iterator_traversal<>
- >::type tuple_of_traversal_tags;
-
- typedef typename tuple_impl_specific::tuple_meta_accumulate<
- tuple_of_traversal_tags
- , minimum_category<>
- , random_access_traversal_tag
- >::type type;
- };
- #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) // ETI workaround
- template <>
- struct minimum_traversal_category_in_iterator_tuple<int>
- {
- typedef int type;
- };
- #endif
-
- // We need to call tuple_meta_accumulate with mpl::and_ as the
- // accumulating functor. To this end, we need to wrap it into
- // a struct that has exactly two arguments (that is, template
- // parameters) and not five, like mpl::and_ does.
- //
- template<typename Arg1, typename Arg2>
- struct and_with_two_args
- : mpl::and_<Arg1, Arg2>
- {
- };
-
- # ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
- // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
- // out well. In this case I think it's an MPL bug
- template<>
- struct and_with_two_args<mpl::_1,mpl::_2>
- {
- template <class A1, class A2>
- struct apply : mpl::and_<A1,A2>
- {};
- };
- # endif
- ///////////////////////////////////////////////////////////////////
- //
- // 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_traits<
- typename tuples::element<0, IteratorTuple>::type
- >::difference_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;
- };
- }
-
- /////////////////////////////////////////////////////////////////////
- //
- // 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
- {
- return detail::tuple_impl_specific::tuple_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 detail::tuple_impl_specific::tuple_equal(
- 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)
- {
- detail::tuple_impl_specific::tuple_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()
- {
- detail::tuple_impl_specific::tuple_for_each(
- m_iterator_tuple,
- detail::increment_iterator()
- );
- }
-
- // Decrementing a zip iterator means to decrement all iterators in
- // the iterator tuple.
- void decrement()
- {
- detail::tuple_impl_specific::tuple_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 boost::tuples::get<0>(other.get_iterator_tuple()) -
- boost::tuples::get<0>(this->get_iterator_tuple());
- }
-
- // Data Members
- // ============
-
- // The iterator tuple.
- IteratorTuple m_iterator_tuple;
-
- };
- // Make function for zip iterator
- //
- template<typename IteratorTuple>
- zip_iterator<IteratorTuple>
- make_zip_iterator(IteratorTuple t)
- { return zip_iterator<IteratorTuple>(t); }
- }
- #endif
|