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