diff options
Diffstat (limited to 'boost/iterator/zip_iterator.hpp')
-rw-r--r-- | boost/iterator/zip_iterator.hpp | 425 |
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 |