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 namespace iterators { 26 27 // 28 // Traversal Categories 29 // 30 31 struct no_traversal_tag {}; 32 33 struct incrementable_traversal_tag 34 : no_traversal_tag 35 { 36 // incrementable_traversal_tag() {} 37 // incrementable_traversal_tag(std::output_iterator_tag const&) {}; 38 }; 39 40 struct single_pass_traversal_tag 41 : incrementable_traversal_tag 42 { 43 // single_pass_traversal_tag() {} 44 // single_pass_traversal_tag(std::input_iterator_tag const&) {}; 45 }; 46 47 struct forward_traversal_tag 48 : single_pass_traversal_tag 49 { 50 // forward_traversal_tag() {} 51 // forward_traversal_tag(std::forward_iterator_tag const&) {}; 52 }; 53 54 struct bidirectional_traversal_tag 55 : forward_traversal_tag 56 { 57 // bidirectional_traversal_tag() {}; 58 // bidirectional_traversal_tag(std::bidirectional_iterator_tag const&) {}; 59 }; 60 61 struct random_access_traversal_tag 62 : bidirectional_traversal_tag 63 { 64 // random_access_traversal_tag() {}; 65 // random_access_traversal_tag(std::random_access_iterator_tag const&) {}; 66 }; 67 68 namespace detail 69 { 70 // 71 // Convert a "strictly old-style" iterator category to a traversal 72 // tag. This is broken out into a separate metafunction to reduce 73 // the cost of instantiating iterator_category_to_traversal, below, 74 // for new-style types. 75 // 76 template <class Cat> 77 struct old_category_to_traversal 78 : mpl::eval_if< 79 is_convertible<Cat,std::random_access_iterator_tag> 80 , mpl::identity<random_access_traversal_tag> 81 , mpl::eval_if< 82 is_convertible<Cat,std::bidirectional_iterator_tag> 83 , mpl::identity<bidirectional_traversal_tag> 84 , mpl::eval_if< 85 is_convertible<Cat,std::forward_iterator_tag> 86 , mpl::identity<forward_traversal_tag> 87 , mpl::eval_if< 88 is_convertible<Cat,std::input_iterator_tag> 89 , mpl::identity<single_pass_traversal_tag> 90 , mpl::eval_if< 91 is_convertible<Cat,std::output_iterator_tag> 92 , mpl::identity<incrementable_traversal_tag> 93 , void 94 > 95 > 96 > 97 > 98 > 99 {}; 100 101 } // namespace detail 102 103 // 104 // Convert an iterator category into a traversal tag 105 // 106 template <class Cat> 107 struct iterator_category_to_traversal 108 : mpl::eval_if< // if already convertible to a traversal tag, we're done. 109 is_convertible<Cat,incrementable_traversal_tag> 110 , mpl::identity<Cat> 111 , boost::iterators::detail::old_category_to_traversal<Cat> 112 > 113 {}; 114 115 // Trait to get an iterator's traversal category 116 template <class Iterator = mpl::_1> 117 struct iterator_traversal 118 : iterator_category_to_traversal< 119 typename boost::detail::iterator_traits<Iterator>::iterator_category 120 > 121 {}; 122 123 # ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT 124 // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work 125 // out well. Instantiating the nested apply template also 126 // requires instantiating iterator_traits on the 127 // placeholder. Instead we just specialize it as a metafunction 128 // class. 129 template <> 130 struct iterator_traversal<mpl::_1> 131 { 132 template <class T> 133 struct apply : iterator_traversal<T> 134 {}; 135 }; 136 template <> 137 struct iterator_traversal<mpl::_> 138 : iterator_traversal<mpl::_1> 139 {}; 140 # endif 141 142 // 143 // Convert an iterator traversal to one of the traversal tags. 144 // 145 template <class Traversal> 146 struct pure_traversal_tag 147 : mpl::eval_if< 148 is_convertible<Traversal,random_access_traversal_tag> 149 , mpl::identity<random_access_traversal_tag> 150 , mpl::eval_if< 151 is_convertible<Traversal,bidirectional_traversal_tag> 152 , mpl::identity<bidirectional_traversal_tag> 153 , mpl::eval_if< 154 is_convertible<Traversal,forward_traversal_tag> 155 , mpl::identity<forward_traversal_tag> 156 , mpl::eval_if< 157 is_convertible<Traversal,single_pass_traversal_tag> 158 , mpl::identity<single_pass_traversal_tag> 159 , mpl::eval_if< 160 is_convertible<Traversal,incrementable_traversal_tag> 161 , mpl::identity<incrementable_traversal_tag> 162 , void 163 > 164 > 165 > 166 > 167 > 168 { 169 }; 170 171 // 172 // Trait to retrieve one of the iterator traversal tags from the iterator category or traversal. 173 // 174 template <class Iterator = mpl::_1> 175 struct pure_iterator_traversal 176 : pure_traversal_tag<typename iterator_traversal<Iterator>::type> 177 {}; 178 179 # ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT 180 template <> 181 struct pure_iterator_traversal<mpl::_1> 182 { 183 template <class T> 184 struct apply : pure_iterator_traversal<T> 185 {}; 186 }; 187 template <> 188 struct pure_iterator_traversal<mpl::_> 189 : pure_iterator_traversal<mpl::_1> 190 {}; 191 # endif 192 193 } // namespace iterators 194 195 using iterators::no_traversal_tag; 196 using iterators::incrementable_traversal_tag; 197 using iterators::single_pass_traversal_tag; 198 using iterators::forward_traversal_tag; 199 using iterators::bidirectional_traversal_tag; 200 using iterators::random_access_traversal_tag; 201 using iterators::iterator_category_to_traversal; 202 using iterators::iterator_traversal; 203 204 // This import is needed for backward compatibility with Boost.Range: 205 // boost/range/detail/demote_iterator_traversal_tag.hpp 206 // It should be removed when that header is fixed. 207 namespace detail { 208 using iterators::pure_traversal_tag; 209 } // namespace detail 210 211 } // namespace boost 212 213 #include <boost/iterator/detail/config_undef.hpp> 214 215 #endif // BOOST_ITERATOR_CATEGORIES_HPP 216