Section 7.4.  Writing Your Own View
Team LiB
Previous Section Next Section

7.4. Writing Your Own View

Since most of a sequence view's smarts are in its iterators, it stands to reason that most of the work of implementing a view involves implementing an iterator adaptor. Let's whip up an iterator for zip_view to see how it's done.

Since zip_view operates on a sequence of input sequences, it's natural that its iterator should operate on a sequence of iterators into those input sequences. Let's give our zip_iterator an iterator sequence parameter:



    template <class IteratorSeq>


    struct zip_iterator;



The MPL's zip_iterator models the least refined concept of any of its component iterators, but for the sake of simplicity our zip_iterator will always be a forward iterator. The only requirements we need to satisfy for a forward iterator are dereferencing with mpl::deref and incrementing with mpl::next. To dereference a zip iterator we need to dereference each of its component iterators and pack the results into a sequence. Taking advantage of the default definition of mpl::deref, which just invokes its argument as a metafunction, the body of zip_iterator is defined thus:



    template <class IteratorSeq>


    struct zip_iterator


    {


        typedef mpl::forward_iterator_tag category;





        typedef typename mpl::transform<


            IteratorSeq


          , mpl::deref<_1>


        >::type type;


    };



Similarly, to increment a zip iterator we need to increment each of its component iterators:



    namespace boost { namespace mpl


    {


      // specialize next<...> for zip_iterator


      template <class IteratorSeq>


      struct next<::zip_iterator<IteratorSeq> >


      {


          typedef ::zip_iterator<


              typename transform<


                  IteratorSeq


                , next<_1>


              >::type


          > type;


      };


    }}



The one remaining element we might want to add to the body of zip_iterator, as a convenience, is a ::base member that accesses the iterators being adapted. In an iterator adaptor for a single iterator, ::base would just be that one iterator; in this case, though, it will be a sequence of underlying iterators:



    template <class IteratorSeq>


    struct zip_iterator


    {


        typedef IteratorSeq base;


        ...


    };



Now there's almost nothing left to do for zip_view; it's just a sequence that uses zip_iterator. In fact, we can build zip_view out of iterator_range:



    template <class Sequences>


    struct zip_view


      : mpl::iterator_range<


            zip_iterator<


                typename mpl::transform_view<


                    Sequences, mpl::begin<_1>


                >::type


            >


          , zip_iterator<


                typename mpl::transform_view<


                    Sequences, mpl::end<_1>


                >::type


            >


        >


    {};



    Team LiB
    Previous Section Next Section