summaryrefslogtreecommitdiff
path: root/boost/iterator/zip_iterator.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/iterator/zip_iterator.hpp')
-rw-r--r--boost/iterator/zip_iterator.hpp425
1 files changed, 110 insertions, 315 deletions
diff --git a/boost/iterator/zip_iterator.hpp b/boost/iterator/zip_iterator.hpp
index 304f65eb2f..83fa63b2a7 100644
--- a/boost/iterator/zip_iterator.hpp
+++ b/boost/iterator/zip_iterator.hpp
@@ -1,6 +1,8 @@
-// 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
+// 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_
@@ -12,19 +14,26 @@
#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/minimum_category.hpp>
-#include <boost/tuple/tuple.hpp>
+#include <utility> // for std::pair
+#include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
-#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/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/mpl/aux_/lambda_support.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 {
@@ -33,24 +42,6 @@ namespace iterators {
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
{
@@ -73,313 +64,96 @@ namespace iterators {
struct increment_iterator
{
template<typename Iterator>
- void operator()(Iterator& it)
+ void operator()(Iterator& it) const
{ ++it; }
};
//
struct decrement_iterator
{
template<typename Iterator>
- void operator()(Iterator& it)
+ void operator()(Iterator& it) const
{ --it; }
};
//
struct dereference_iterator
{
- template<typename Iterator>
- struct apply
+ template<typename>
+ struct result;
+
+ template<typename This, typename Iterator>
+ struct result<This(Iterator)>
{
typedef typename
- boost::detail::iterator_traits<Iterator>::reference
- type;
+ remove_reference<typename remove_cv<Iterator>::type>::type
+ iterator;
+
+ typedef typename iterator_reference<iterator>::type type;
};
template<typename Iterator>
- typename apply<Iterator>::type operator()(Iterator const& it)
+ typename result<dereference_iterator(Iterator)>::type
+ operator()(Iterator const& it) const
{ 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<
- boost::is_same<Tuple, tuples::null_type>
- , 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>
- inline 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>
- inline 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>
- inline 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>
- inline Fun BOOST_TUPLE_ALGO(tuple_for_each)(
- tuples::null_type
- , Fun f BOOST_TUPLE_ALGO_TERMINATOR
- )
- { return f; }
-
-
- template<typename Tuple, typename Fun>
- inline 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>
- inline 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>
- inline 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 boost::detail::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<
+ : 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 tuple_impl_specific::tuple_meta_transform<
+ typedef typename mpl::transform<
IteratorTuple
, pure_traversal_tag<iterator_traversal<> >
>::type tuple_of_traversal_tags;
- typedef typename tuple_impl_specific::tuple_meta_accumulate<
+ typedef typename mpl::fold<
tuple_of_traversal_tags
- , minimum_category<>
, random_access_traversal_tag
+ , minimum_category<>
>::type type;
};
- // 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
+ 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;
+ };
///////////////////////////////////////////////////////////////////
//
@@ -401,9 +175,9 @@ namespace iterators {
typedef reference value_type;
// Difference type is the first iterator's difference type
- typedef typename boost::detail::iterator_traits<
- typename tuples::element<0, IteratorTuple>::type
- >::difference_type 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.
@@ -429,6 +203,30 @@ namespace iterators {
{
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));
+ }
+ };
}
/////////////////////////////////////////////////////////////////////
@@ -484,10 +282,11 @@ namespace iterators {
// iterators in the iterator tuple.
typename super_t::reference dereference() const
{
- return detail::tuple_impl_specific::tuple_transform(
- get_iterator_tuple(),
- detail::dereference_iterator()
- );
+ 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
@@ -503,39 +302,35 @@ namespace iterators {
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()
- );
+ 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)
{
- detail::tuple_impl_specific::tuple_for_each(
+ fusion::for_each(
m_iterator_tuple,
- detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n)
- );
+ 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()
- );
+ fusion::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()
- );
+ fusion::for_each(
+ m_iterator_tuple,
+ detail::decrement_iterator());
}
// Distance is calculated using the first iterator in the tuple.
@@ -544,8 +339,8 @@ namespace iterators {
const zip_iterator<OtherIteratorTuple>& other
) const
{
- return boost::tuples::get<0>(other.get_iterator_tuple()) -
- boost::tuples::get<0>(this->get_iterator_tuple());
+ return fusion::at_c<0>(other.get_iterator_tuple()) -
+ fusion::at_c<0>(this->get_iterator_tuple());
}
// Data Members