Ticket #7526: zip_iterator.patch

File zip_iterator.patch, 19.4 KB (added by Kohei Takahashi <flast@…>, 10 years ago)
  • boost/iterator/zip_iterator.hpp

    From 69cb714a69a3a9335cf4c38e38343bbd8b160391 Mon Sep 17 00:00:00 2001
    From: Kohei Takahashi <flast@flast.jp>
    Date: Wed, 17 Oct 2012 18:09:08 +0900
    Subject: [PATCH] boost::zip_iterator rebase to Boost.Fusion
    
    ---
     boost/iterator/zip_iterator.hpp          |  433 +++++++-----------------------
     libs/iterator/test/zip_iterator_test.cpp |    2 +
     2 files changed, 96 insertions(+), 339 deletions(-)
    
    diff --git a/boost/iterator/zip_iterator.hpp b/boost/iterator/zip_iterator.hpp
    index a468070..28785e6 100644
    a b  
    1 // Copyright David Abrahams and Thomas Becker 2000-2006. Distributed
    2 // under the Boost Software License, Version 1.0. (See accompanying
    3 // file LICENSE_1_0.txt or copy at
     1// Copyright David Abrahams and Thomas Becker 2000-2006.
     2// Copyright Kohei Takahashi 2012.
     3//
     4// Distributed under the Boost Software License, Version 1.0. (See
     5// accompanying file LICENSE_1_0.txt or copy at
    46// http://www.boost.org/LICENSE_1_0.txt)
    57
    68#ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_
     
    1618
    1719#include <boost/iterator/detail/minimum_category.hpp>
    1820
    19 #include <boost/tuple/tuple.hpp>
     21#include <boost/fusion/adapted/boost_tuple.hpp> // for backward compatibility
    2022
    21 #include <boost/type_traits/is_same.hpp>
    22 #include <boost/mpl/and.hpp>
    23 #include <boost/mpl/apply.hpp>
    24 #include <boost/mpl/eval_if.hpp>
    25 #include <boost/mpl/lambda.hpp>
     23#include <boost/type_traits/remove_reference.hpp>
     24#include <boost/type_traits/remove_cv.hpp>
     25
     26#include <boost/mpl/at.hpp>
     27#include <boost/mpl/fold.hpp>
     28#include <boost/mpl/transform.hpp>
    2629#include <boost/mpl/placeholders.hpp>
    2730#include <boost/mpl/aux_/lambda_support.hpp>
    2831
     32#include <boost/fusion/algorithm/iteration/for_each.hpp>
     33#include <boost/fusion/algorithm/transformation/transform.hpp>
     34#include <boost/fusion/sequence/convert.hpp>
     35#include <boost/fusion/sequence/intrinsic/at_c.hpp>
     36#include <boost/fusion/sequence/comparison/equal_to.hpp>
     37#include <boost/fusion/support/tag_of_fwd.hpp>
     38
    2939namespace boost {
    3040
    3141  // Zip iterator forward declaration for zip_iterator_base
    3242  template<typename IteratorTuple>
    3343  class zip_iterator;
    3444
    35   // One important design goal of the zip_iterator is to isolate all
    36   // functionality whose implementation relies on the current tuple
    37   // implementation. This goal has been achieved as follows: Inside
    38   // the namespace detail there is a namespace tuple_impl_specific.
    39   // This namespace encapsulates all functionality that is specific
    40   // to the current Boost tuple implementation. More precisely, the
    41   // namespace tuple_impl_specific provides the following tuple
    42   // algorithms and meta-algorithms for the current Boost tuple
    43   // implementation:
    44   //
    45   // tuple_meta_transform
    46   // tuple_meta_accumulate
    47   // tuple_transform
    48   // tuple_for_each
    49   //
    50   // If the tuple implementation changes, all that needs to be
    51   // replaced is the implementation of these four (meta-)algorithms.
    52 
    5345  namespace detail
    5446  {
    5547
    namespace boost {  
    6052    {
    6153    public:
    6254      advance_iterator(DiffType step) : m_step(step) {}
    63      
     55
    6456      template<typename Iterator>
    6557      void operator()(Iterator& it) const
    6658      { it += m_step; }
    namespace boost {  
    7264    struct increment_iterator
    7365    {
    7466      template<typename Iterator>
    75       void operator()(Iterator& it)
     67      void operator()(Iterator& it) const
    7668      { ++it; }
    7769    };
    7870    //
    7971    struct decrement_iterator
    8072    {
    8173      template<typename Iterator>
    82       void operator()(Iterator& it)
     74      void operator()(Iterator& it) const
    8375      { --it; }
    8476    };
    8577    //
    8678    struct dereference_iterator
    8779    {
    88       template<typename Iterator>
    89       struct apply
    90       {
     80      template<typename>
     81      struct result;
     82
     83      template<typename This, typename Iterator>
     84      struct result<This(Iterator)>
     85      {
     86        typedef typename
     87          remove_reference<typename remove_cv<Iterator>::type>::type
     88        iterator;
     89
    9190        typedef typename
    92           iterator_traits<Iterator>::reference
     91          iterator_traits<iterator>::reference
    9392        type;
    9493      };
    9594
    9695      template<typename Iterator>
    97         typename apply<Iterator>::type operator()(Iterator const& it)
     96        typename result<dereference_iterator(Iterator)>::type
     97        operator()(Iterator const& it) const
    9898      { return *it; }
    9999    };
    100            
    101 
    102     // The namespace tuple_impl_specific provides two meta-
    103     // algorithms and two algorithms for tuples.
    104     //
    105     namespace tuple_impl_specific
    106     {
    107       // Meta-transform algorithm for tuples
    108       //
    109       template<typename Tuple, class UnaryMetaFun>
    110       struct tuple_meta_transform;
    111      
    112       template<typename Tuple, class UnaryMetaFun>
    113       struct tuple_meta_transform_impl
    114       {
    115           typedef tuples::cons<
    116               typename mpl::apply1<
    117                   typename mpl::lambda<UnaryMetaFun>::type
    118                 , typename Tuple::head_type
    119               >::type
    120             , typename tuple_meta_transform<
    121                   typename Tuple::tail_type
    122                 , UnaryMetaFun
    123               >::type
    124           > type;
    125       };
    126 
    127       template<typename Tuple, class UnaryMetaFun>
    128       struct tuple_meta_transform
    129         : mpl::eval_if<
    130               boost::is_same<Tuple, tuples::null_type>
    131             , mpl::identity<tuples::null_type>
    132             , tuple_meta_transform_impl<Tuple, UnaryMetaFun>
    133         >
    134       {
    135       };
    136      
    137       // Meta-accumulate algorithm for tuples. Note: The template
    138       // parameter StartType corresponds to the initial value in
    139       // ordinary accumulation.
    140       //
    141       template<class Tuple, class BinaryMetaFun, class StartType>
    142       struct tuple_meta_accumulate;
    143      
    144       template<
    145           typename Tuple
    146         , class BinaryMetaFun
    147         , typename StartType
    148       >
    149       struct tuple_meta_accumulate_impl
    150       {
    151          typedef typename mpl::apply2<
    152              typename mpl::lambda<BinaryMetaFun>::type
    153            , typename Tuple::head_type
    154            , typename tuple_meta_accumulate<
    155                  typename Tuple::tail_type
    156                , BinaryMetaFun
    157                , StartType
    158              >::type
    159          >::type type;
    160       };
    161 
    162       template<
    163           typename Tuple
    164         , class BinaryMetaFun
    165         , typename StartType
    166       >
    167       struct tuple_meta_accumulate
    168         : mpl::eval_if<
    169 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
    170               mpl::or_<
    171 #endif
    172                   boost::is_same<Tuple, tuples::null_type>
    173 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
    174                 , boost::is_same<Tuple,int>
    175               >
    176 #endif
    177             , mpl::identity<StartType>
    178             , tuple_meta_accumulate_impl<
    179                   Tuple
    180                 , BinaryMetaFun
    181                 , StartType
    182               >
    183           >
    184       {
    185       }; 
    186 
    187 #if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)                            \
    188     || (                                                                    \
    189       BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, != 0) && defined(_MSC_VER)  \
    190     )
    191 // Not sure why intel's partial ordering fails in this case, but I'm
    192 // assuming int's an MSVC bug-compatibility feature.
    193      
    194 # define BOOST_TUPLE_ALGO_DISPATCH
    195 # define BOOST_TUPLE_ALGO(algo) algo##_impl
    196 # define BOOST_TUPLE_ALGO_TERMINATOR , int
    197 # define BOOST_TUPLE_ALGO_RECURSE , ...
    198 #else
    199 # define BOOST_TUPLE_ALGO(algo) algo
    200 # define BOOST_TUPLE_ALGO_TERMINATOR
    201 # define BOOST_TUPLE_ALGO_RECURSE
    202 #endif
    203      
    204       // transform algorithm for tuples. The template parameter Fun
    205       // must be a unary functor which is also a unary metafunction
    206       // class that computes its return type based on its argument
    207       // type. For example:
    208       //
    209       // struct to_ptr
    210       // {
    211       //     template <class Arg>
    212       //     struct apply
    213       //     {
    214       //          typedef Arg* type;
    215       //     }
    216       //
    217       //     template <class Arg>
    218       //     Arg* operator()(Arg x);
    219       // };
    220       template<typename Fun>
    221       tuples::null_type BOOST_TUPLE_ALGO(tuple_transform)
    222           (tuples::null_type const&, Fun BOOST_TUPLE_ALGO_TERMINATOR)
    223       { return tuples::null_type(); }
    224 
    225       template<typename Tuple, typename Fun>
    226       typename tuple_meta_transform<
    227           Tuple
    228         , Fun
    229       >::type
    230      
    231       BOOST_TUPLE_ALGO(tuple_transform)(
    232         const Tuple& t,
    233         Fun f
    234         BOOST_TUPLE_ALGO_RECURSE
    235       )
    236       {
    237           typedef typename tuple_meta_transform<
    238               BOOST_DEDUCED_TYPENAME Tuple::tail_type
    239             , Fun
    240           >::type transformed_tail_type;
    241 
    242         return tuples::cons<
    243             BOOST_DEDUCED_TYPENAME mpl::apply1<
    244                 Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type
    245              >::type
    246            , transformed_tail_type
    247         >(
    248             f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f)
    249         );
    250       }
    251 
    252 #ifdef BOOST_TUPLE_ALGO_DISPATCH
    253       template<typename Tuple, typename Fun>
    254       typename tuple_meta_transform<
    255           Tuple
    256         , Fun
    257       >::type
    258      
    259       tuple_transform(
    260         const Tuple& t,
    261         Fun f
    262       )
    263       {
    264           return tuple_transform_impl(t, f, 1);
    265       }
    266 #endif
    267      
    268       // for_each algorithm for tuples.
    269       //
    270       template<typename Fun>
    271       Fun BOOST_TUPLE_ALGO(tuple_for_each)(
    272           tuples::null_type
    273         , Fun f BOOST_TUPLE_ALGO_TERMINATOR
    274       )
    275       { return f; }
    276 
    277      
    278       template<typename Tuple, typename Fun>
    279       Fun BOOST_TUPLE_ALGO(tuple_for_each)(
    280           Tuple& t
    281         , Fun f BOOST_TUPLE_ALGO_RECURSE)
    282       {
    283           f( t.get_head() );
    284           return tuple_for_each(t.get_tail(), f);
    285       }
    286      
    287 #ifdef BOOST_TUPLE_ALGO_DISPATCH
    288       template<typename Tuple, typename Fun>
    289       Fun
    290       tuple_for_each(
    291         Tuple& t,
    292         Fun f
    293       )
    294       {
    295           return tuple_for_each_impl(t, f, 1);
    296       }
    297 #endif
    298      
    299       // Equality of tuples. NOTE: "==" for tuples currently (7/2003)
    300       // has problems under some compilers, so I just do my own.
    301       // No point in bringing in a bunch of #ifdefs here. This is
    302       // going to go away with the next tuple implementation anyway.
    303       //
    304       inline bool tuple_equal(tuples::null_type, tuples::null_type)
    305       { return true; }
    306 
    307       template<typename Tuple1, typename Tuple2>
    308         bool tuple_equal(
    309             Tuple1 const& t1,
    310             Tuple2 const& t2
    311         )
    312       {
    313           return t1.get_head() == t2.get_head() &&
    314           tuple_equal(t1.get_tail(), t2.get_tail());
    315       }
    316     }
    317     //
    318     // end namespace tuple_impl_specific
    319100
    320101    template<typename Iterator>
    321102    struct iterator_reference
    namespace boost {  
    336117        struct apply : iterator_reference<T> {};
    337118    };
    338119#endif
    339    
     120
    340121    // Metafunction to obtain the type of the tuple whose element types
    341122    // are the reference types of an iterator tuple.
    342123    //
    343124    template<typename IteratorTuple>
    344125    struct tuple_of_references
    345       : tuple_impl_specific::tuple_meta_transform<
    346             IteratorTuple, 
     126      : mpl::transform<
     127            IteratorTuple,
    347128            iterator_reference<mpl::_1>
    348129          >
    349130    {
    namespace boost {  
    355136    template<typename IteratorTuple>
    356137    struct minimum_traversal_category_in_iterator_tuple
    357138    {
    358       typedef typename tuple_impl_specific::tuple_meta_transform<
     139      typedef typename mpl::transform<
    359140          IteratorTuple
    360141        , pure_traversal_tag<iterator_traversal<> >
    361142      >::type tuple_of_traversal_tags;
    362          
    363       typedef typename tuple_impl_specific::tuple_meta_accumulate<
     143
     144      typedef typename mpl::fold<
    364145          tuple_of_traversal_tags
    365         , minimum_category<>
    366146        , random_access_traversal_tag
     147        , minimum_category<>
    367148      >::type type;
    368149    };
    369150
    namespace boost {  
    374155          typedef int type;
    375156      };
    376157#endif
    377      
    378       // We need to call tuple_meta_accumulate with mpl::and_ as the
    379       // accumulating functor. To this end, we need to wrap it into
    380       // a struct that has exactly two arguments (that is, template
    381       // parameters) and not five, like mpl::and_ does.
    382       //
    383       template<typename Arg1, typename Arg2>
    384       struct and_with_two_args
    385         : mpl::and_<Arg1, Arg2>
    386       {
    387       };
    388    
    389 # ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
    390   // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
    391   // out well.  In this case I think it's an MPL bug
    392       template<>
    393       struct and_with_two_args<mpl::_1,mpl::_2>
    394       {
    395           template <class A1, class A2>
    396           struct apply : mpl::and_<A1,A2>
    397           {};
    398       };
    399 # endif
    400158
    401159    ///////////////////////////////////////////////////////////////////
    402160    //
    403161    // Class zip_iterator_base
    404162    //
    405     // Builds and exposes the iterator facade type from which the zip 
     163    // Builds and exposes the iterator facade type from which the zip
    406164    // iterator will be derived.
    407165    //
    408166    template<typename IteratorTuple>
    namespace boost {  
    411169     private:
    412170        // Reference type is the type of the tuple obtained from the
    413171        // iterators' reference types.
    414         typedef typename 
     172        typedef typename
    415173        detail::tuple_of_references<IteratorTuple>::type reference;
    416      
     174
    417175        // Value type is the same as reference type.
    418176        typedef reference value_type;
    419      
     177
    420178        // Difference type is the first iterator's difference type
    421179        typedef typename iterator_traits<
    422             typename tuples::element<0, IteratorTuple>::type
     180            typename mpl::at_c<IteratorTuple, 0>::type
    423181            >::difference_type difference_type;
    424      
    425         // Traversal catetgory is the minimum traversal category in the 
     182
     183        // Traversal catetgory is the minimum traversal category in the
    426184        // iterator tuple.
    427         typedef typename 
     185        typedef typename
    428186        detail::minimum_traversal_category_in_iterator_tuple<
    429187            IteratorTuple
    430188        >::type traversal_category;
    431189     public:
    432      
     190
    433191        // The iterator facade type from which the zip iterator will
    434192        // be derived.
    435193        typedef iterator_facade<
    436194            zip_iterator<IteratorTuple>,
    437             value_type, 
     195            value_type,
    438196            traversal_category,
    439197            reference,
    440198            difference_type
    namespace boost {  
    447205        typedef int type;
    448206    };
    449207  }
    450  
     208
    451209  /////////////////////////////////////////////////////////////////////
    452210  //
    453211  // zip_iterator class definition
    454212  //
    455213  template<typename IteratorTuple>
    456   class zip_iterator : 
     214  class zip_iterator :
    457215    public detail::zip_iterator_base<IteratorTuple>::type
    458   { 
     216  {
    459217
    460    // Typedef super_t as our base class. 
    461    typedef typename 
     218   // Typedef super_t as our base class.
     219   typedef typename
    462220     detail::zip_iterator_base<IteratorTuple>::type super_t;
    463221
    464222   // iterator_core_access is the iterator's best friend.
    465223   friend class iterator_core_access;
    466224
    467225  public:
    468    
     226
    469227    // Construction
    470228    // ============
    471    
     229
    472230    // Default constructor
    473231    zip_iterator() { }
    474232
    475233    // Constructor from iterator tuple
    476     zip_iterator(IteratorTuple iterator_tuple) 
    477       : m_iterator_tuple(iterator_tuple) 
     234    zip_iterator(IteratorTuple iterator_tuple)
     235      : m_iterator_tuple(iterator_tuple)
    478236    { }
    479237
    480238    // Copy constructor
    namespace boost {  
    493251    { return m_iterator_tuple; }
    494252
    495253  private:
    496    
     254
    497255    // Implementation of Iterator Operations
    498256    // =====================================
    499    
     257
    500258    // Dereferencing returns a tuple built from the dereferenced
    501259    // iterators in the iterator tuple.
    502260    typename super_t::reference dereference() const
    503     {
    504       return detail::tuple_impl_specific::tuple_transform(
    505         get_iterator_tuple(),
    506         detail::dereference_iterator()
    507        );
     261    {
     262        typedef typename super_t::reference reference;
     263        typedef typename fusion::traits::tag_of<reference>::type tag;
     264        return fusion::convert<tag>(fusion::transform(
     265          get_iterator_tuple(),
     266          detail::dereference_iterator()));
    508267    }
    509268
    510269    // Two zip iterators are equal if all iterators in the iterator
    namespace boost {  
    517276    // under several compilers. No point in bringing in a bunch
    518277    // of #ifdefs here.
    519278    //
    520     template<typename OtherIteratorTuple>   
     279    template<typename OtherIteratorTuple>
    521280    bool equal(const zip_iterator<OtherIteratorTuple>& other) const
    522281    {
    523       return detail::tuple_impl_specific::tuple_equal(
    524         get_iterator_tuple(),
    525         other.get_iterator_tuple()
    526         );
     282        return fusion::equal_to(
     283          get_iterator_tuple(),
     284          other.get_iterator_tuple());
    527285    }
    528286
    529287    // Advancing a zip iterator means to advance all iterators in the
    530288    // iterator tuple.
    531289    void advance(typename super_t::difference_type n)
    532     { 
    533       detail::tuple_impl_specific::tuple_for_each(
     290    {
     291        fusion::for_each(
    534292          m_iterator_tuple,
    535           detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n)
    536           );
     293          detail::advance_iterator<BOOST_DEDUCED_TYPENAME super_t::difference_type>(n));
    537294    }
    538295    // Incrementing a zip iterator means to increment all iterators in
    539296    // the iterator tuple.
    540297    void increment()
    541     {
    542       detail::tuple_impl_specific::tuple_for_each(
    543         m_iterator_tuple,
    544         detail::increment_iterator()
    545         );
     298    {
     299        fusion::for_each(
     300          m_iterator_tuple,
     301          detail::increment_iterator());
    546302    }
    547    
     303
    548304    // Decrementing a zip iterator means to decrement all iterators in
    549305    // the iterator tuple.
    550306    void decrement()
    551     {
    552       detail::tuple_impl_specific::tuple_for_each(
    553         m_iterator_tuple,
    554         detail::decrement_iterator()
    555         );
     307    {
     308        fusion::for_each(
     309          m_iterator_tuple,
     310          detail::decrement_iterator());
    556311    }
    557    
     312
    558313    // Distance is calculated using the first iterator in the tuple.
    559314    template<typename OtherIteratorTuple>
    560315      typename super_t::difference_type distance_to(
    561316        const zip_iterator<OtherIteratorTuple>& other
    562317        ) const
    563     { 
    564         return boost::tuples::get<0>(other.get_iterator_tuple()) -
    565             boost::tuples::get<0>(this->get_iterator_tuple());
     318    {
     319        return fusion::at_c<0>(other.get_iterator_tuple()) -
     320            fusion::at_c<0>(this->get_iterator_tuple());
    566321    }
    567  
     322
    568323    // Data Members
    569324    // ============
    570    
     325
    571326    // The iterator tuple.
    572327    IteratorTuple m_iterator_tuple;
    573  
     328
    574329  };
    575330
    576331  // Make function for zip iterator
    577332  //
    578   template<typename IteratorTuple> 
    579   zip_iterator<IteratorTuple> 
     333  template<typename IteratorTuple>
     334  zip_iterator<IteratorTuple>
    580335  make_zip_iterator(IteratorTuple t)
    581336  { return zip_iterator<IteratorTuple>(t); }
    582337
  • libs/iterator/test/zip_iterator_test.cpp

    diff --git a/libs/iterator/test/zip_iterator_test.cpp b/libs/iterator/test/zip_iterator_test.cpp
    index 8062f08..3f56b16 100644
    a b  
    4949#include <string>
    5050#include <functional>
    5151#include <boost/tuple/tuple.hpp>
     52#include <boost/fusion/adapted/boost_tuple.hpp>
     53#include <boost/fusion/mpl.hpp>
    5254#include <boost/iterator/transform_iterator.hpp>
    5355#include <boost/iterator/is_readable_iterator.hpp>
    5456#include <boost/type_traits/is_same.hpp>