1 // Copyright David Abrahams 2003. Use, modification and distribution is 2 // subject to the Boost Software License, Version 1.0. (See accompanying 3 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 4 #ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP 5 # define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP 6 7 # include <boost/iterator/iterator_categories.hpp> 8 9 # include <boost/mpl/or.hpp> // used in iterator_tag inheritance logic 10 # include <boost/mpl/and.hpp> 11 # include <boost/mpl/if.hpp> 12 # include <boost/mpl/eval_if.hpp> 13 # include <boost/mpl/identity.hpp> 14 # include <boost/mpl/assert.hpp> 15 16 # include <boost/type_traits/is_same.hpp> 17 # include <boost/type_traits/is_const.hpp> 18 # include <boost/type_traits/is_reference.hpp> 19 # include <boost/type_traits/is_convertible.hpp> 20 21 # include <boost/type_traits/is_same.hpp> 22 23 # include <boost/iterator/detail/config_def.hpp> // try to keep this last 24 25 # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 26 # include <boost/detail/indirect_traits.hpp> 27 # endif 28 29 // 30 // iterator_category deduction for iterator_facade 31 // 32 33 namespace boost { 34 namespace iterators { 35 36 // forward declaration 37 struct use_default; 38 39 namespace detail { 40 41 struct input_output_iterator_tag 42 : std::input_iterator_tag 43 { 44 // Using inheritance for only input_iterator_tag helps to avoid 45 // ambiguities when a stdlib implementation dispatches on a 46 // function which is overloaded on both input_iterator_tag and 47 // output_iterator_tag, as STLPort does, in its __valid_range 48 // function. I claim it's better to avoid the ambiguity in these 49 // cases. operator std::output_iterator_tagboost::iterators::detail::input_output_iterator_tag50 operator std::output_iterator_tag() const 51 { 52 return std::output_iterator_tag(); 53 } 54 }; 55 56 // 57 // True iff the user has explicitly disabled writability of this 58 // iterator. Pass the iterator_facade's Value parameter and its 59 // nested ::reference type. 60 // 61 template <class ValueParam, class Reference> 62 struct iterator_writability_disabled 63 # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic? 64 : mpl::or_< 65 is_const<Reference> 66 , boost::detail::indirect_traits::is_reference_to_const<Reference> 67 , is_const<ValueParam> 68 > 69 # else 70 : is_const<ValueParam> 71 # endif 72 {}; 73 74 75 // 76 // Convert an iterator_facade's traversal category, Value parameter, 77 // and ::reference type to an appropriate old-style category. 78 // 79 // Due to changeset 21683, this now never results in a category convertible 80 // to output_iterator_tag. 81 // 82 // Change at: https://svn.boost.org/trac/boost/changeset/21683 83 template <class Traversal, class ValueParam, class Reference> 84 struct iterator_facade_default_category 85 : mpl::eval_if< 86 mpl::and_< 87 is_reference<Reference> 88 , is_convertible<Traversal,forward_traversal_tag> 89 > 90 , mpl::eval_if< 91 is_convertible<Traversal,random_access_traversal_tag> 92 , mpl::identity<std::random_access_iterator_tag> 93 , mpl::if_< 94 is_convertible<Traversal,bidirectional_traversal_tag> 95 , std::bidirectional_iterator_tag 96 , std::forward_iterator_tag 97 > 98 > 99 , typename mpl::eval_if< 100 mpl::and_< 101 is_convertible<Traversal, single_pass_traversal_tag> 102 103 // check for readability 104 , is_convertible<Reference, ValueParam> 105 > 106 , mpl::identity<std::input_iterator_tag> 107 , mpl::identity<Traversal> 108 > 109 > 110 { 111 }; 112 113 // True iff T is convertible to an old-style iterator category. 114 template <class T> 115 struct is_iterator_category 116 : mpl::or_< 117 is_convertible<T,std::input_iterator_tag> 118 , is_convertible<T,std::output_iterator_tag> 119 > 120 { 121 }; 122 123 template <class T> 124 struct is_iterator_traversal 125 : is_convertible<T,incrementable_traversal_tag> 126 {}; 127 128 // 129 // A composite iterator_category tag convertible to Category (a pure 130 // old-style category) and Traversal (a pure traversal tag). 131 // Traversal must be a strict increase of the traversal power given by 132 // Category. 133 // 134 template <class Category, class Traversal> 135 struct iterator_category_with_traversal 136 : Category, Traversal 137 { 138 // Make sure this isn't used to build any categories where 139 // convertibility to Traversal is redundant. Should just use the 140 // Category element in that case. 141 BOOST_MPL_ASSERT_NOT(( 142 is_convertible< 143 typename iterator_category_to_traversal<Category>::type 144 , Traversal 145 >)); 146 147 BOOST_MPL_ASSERT((is_iterator_category<Category>)); 148 BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>)); 149 BOOST_MPL_ASSERT_NOT((is_iterator_traversal<Category>)); 150 # if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) 151 BOOST_MPL_ASSERT((is_iterator_traversal<Traversal>)); 152 # endif 153 }; 154 155 // Computes an iterator_category tag whose traversal is Traversal and 156 // which is appropriate for an iterator 157 template <class Traversal, class ValueParam, class Reference> 158 struct facade_iterator_category_impl 159 { 160 BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>)); 161 162 typedef typename iterator_facade_default_category< 163 Traversal,ValueParam,Reference 164 >::type category; 165 166 typedef typename mpl::if_< 167 is_same< 168 Traversal 169 , typename iterator_category_to_traversal<category>::type 170 > 171 , category 172 , iterator_category_with_traversal<category,Traversal> 173 >::type type; 174 }; 175 176 // 177 // Compute an iterator_category for iterator_facade 178 // 179 template <class CategoryOrTraversal, class ValueParam, class Reference> 180 struct facade_iterator_category 181 : mpl::eval_if< 182 is_iterator_category<CategoryOrTraversal> 183 , mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is 184 , facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference> 185 > 186 { 187 }; 188 189 }}} // namespace boost::iterators::detail 190 191 # include <boost/iterator/detail/config_undef.hpp> 192 193 #endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP 194