Home | History | Annotate | Download | only in iterator
      1 // (C) Copyright Jeremy Siek 2002.
      2 // Distributed under the Boost Software License, Version 1.0. (See
      3 // accompanying file LICENSE_1_0.txt or copy at
      4 // http://www.boost.org/LICENSE_1_0.txt)
      5 
      6 #ifndef BOOST_ITERATOR_CATEGORIES_HPP
      7 # define BOOST_ITERATOR_CATEGORIES_HPP
      8 
      9 # include <boost/config.hpp>
     10 # include <boost/detail/iterator.hpp>
     11 # include <boost/iterator/detail/config_def.hpp>
     12 
     13 # include <boost/detail/workaround.hpp>
     14 
     15 # include <boost/mpl/eval_if.hpp>
     16 # include <boost/mpl/identity.hpp>
     17 # include <boost/mpl/placeholders.hpp>
     18 # include <boost/mpl/aux_/lambda_support.hpp>
     19 
     20 # include <boost/type_traits/is_convertible.hpp>
     21 
     22 # include <boost/static_assert.hpp>
     23 
     24 namespace boost {
     25 
     26 //
     27 // Traversal Categories
     28 //
     29 
     30 struct no_traversal_tag {};
     31 
     32 struct incrementable_traversal_tag
     33   : no_traversal_tag
     34 {
     35 //     incrementable_traversal_tag() {}
     36 //     incrementable_traversal_tag(std::output_iterator_tag const&) {};
     37 };
     38 
     39 struct single_pass_traversal_tag
     40   : incrementable_traversal_tag
     41 {
     42 //     single_pass_traversal_tag() {}
     43 //     single_pass_traversal_tag(std::input_iterator_tag const&) {};
     44 };
     45 
     46 struct forward_traversal_tag
     47   : single_pass_traversal_tag
     48 {
     49 //     forward_traversal_tag() {}
     50 //     forward_traversal_tag(std::forward_iterator_tag const&) {};
     51 };
     52 
     53 struct bidirectional_traversal_tag
     54   : forward_traversal_tag
     55 {
     56 //     bidirectional_traversal_tag() {};
     57 //     bidirectional_traversal_tag(std::bidirectional_iterator_tag const&) {};
     58 };
     59 
     60 struct random_access_traversal_tag
     61   : bidirectional_traversal_tag
     62 {
     63 //     random_access_traversal_tag() {};
     64 //     random_access_traversal_tag(std::random_access_iterator_tag const&) {};
     65 };
     66 
     67 namespace detail
     68 {
     69   //
     70   // Convert a "strictly old-style" iterator category to a traversal
     71   // tag.  This is broken out into a separate metafunction to reduce
     72   // the cost of instantiating iterator_category_to_traversal, below,
     73   // for new-style types.
     74   //
     75   template <class Cat>
     76   struct old_category_to_traversal
     77     : mpl::eval_if<
     78           is_convertible<Cat,std::random_access_iterator_tag>
     79         , mpl::identity<random_access_traversal_tag>
     80         , mpl::eval_if<
     81               is_convertible<Cat,std::bidirectional_iterator_tag>
     82             , mpl::identity<bidirectional_traversal_tag>
     83             , mpl::eval_if<
     84                   is_convertible<Cat,std::forward_iterator_tag>
     85                 , mpl::identity<forward_traversal_tag>
     86                 , mpl::eval_if<
     87                       is_convertible<Cat,std::input_iterator_tag>
     88                     , mpl::identity<single_pass_traversal_tag>
     89                     , mpl::eval_if<
     90                           is_convertible<Cat,std::output_iterator_tag>
     91                         , mpl::identity<incrementable_traversal_tag>
     92                         , void
     93                       >
     94                   >
     95               >
     96           >
     97       >
     98   {};
     99 
    100 # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
    101   template <>
    102   struct old_category_to_traversal<int>
    103   {
    104       typedef int type;
    105   };
    106 # endif
    107 
    108   template <class Traversal>
    109   struct pure_traversal_tag
    110     : mpl::eval_if<
    111           is_convertible<Traversal,random_access_traversal_tag>
    112         , mpl::identity<random_access_traversal_tag>
    113         , mpl::eval_if<
    114               is_convertible<Traversal,bidirectional_traversal_tag>
    115             , mpl::identity<bidirectional_traversal_tag>
    116             , mpl::eval_if<
    117                   is_convertible<Traversal,forward_traversal_tag>
    118                 , mpl::identity<forward_traversal_tag>
    119                 , mpl::eval_if<
    120                       is_convertible<Traversal,single_pass_traversal_tag>
    121                     , mpl::identity<single_pass_traversal_tag>
    122                     , mpl::eval_if<
    123                           is_convertible<Traversal,incrementable_traversal_tag>
    124                         , mpl::identity<incrementable_traversal_tag>
    125                         , void
    126                       >
    127                   >
    128               >
    129           >
    130       >
    131   {
    132   };
    133 
    134 # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
    135   template <>
    136   struct pure_traversal_tag<int>
    137   {
    138       typedef int type;
    139   };
    140 # endif
    141 
    142 } // namespace detail
    143 
    144 
    145 //
    146 // Convert an iterator category into a traversal tag
    147 //
    148 template <class Cat>
    149 struct iterator_category_to_traversal
    150   : mpl::eval_if< // if already convertible to a traversal tag, we're done.
    151         is_convertible<Cat,incrementable_traversal_tag>
    152       , mpl::identity<Cat>
    153       , boost::detail::old_category_to_traversal<Cat>
    154     >
    155 {};
    156 
    157 // Trait to get an iterator's traversal category
    158 template <class Iterator = mpl::_1>
    159 struct iterator_traversal
    160   : iterator_category_to_traversal<
    161         typename boost::detail::iterator_traits<Iterator>::iterator_category
    162     >
    163 {};
    164 
    165 # ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
    166 // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
    167 // out well.  Instantiating the nested apply template also
    168 // requires instantiating iterator_traits on the
    169 // placeholder. Instead we just specialize it as a metafunction
    170 // class.
    171 template <>
    172 struct iterator_traversal<mpl::_1>
    173 {
    174     template <class T>
    175     struct apply : iterator_traversal<T>
    176     {};
    177 };
    178 template <>
    179 struct iterator_traversal<mpl::_>
    180   : iterator_traversal<mpl::_1>
    181 {};
    182 # endif
    183 
    184 } // namespace boost
    185 
    186 #include <boost/iterator/detail/config_undef.hpp>
    187 
    188 #endif // BOOST_ITERATOR_CATEGORIES_HPP
    189