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 // forward declaration 34 namespace boost { struct use_default; } 35 36 namespace boost { namespace detail { 37 38 struct input_output_iterator_tag 39 : std::input_iterator_tag 40 { 41 // Using inheritance for only input_iterator_tag helps to avoid 42 // ambiguities when a stdlib implementation dispatches on a 43 // function which is overloaded on both input_iterator_tag and 44 // output_iterator_tag, as STLPort does, in its __valid_range 45 // function. I claim it's better to avoid the ambiguity in these 46 // cases. operator std::output_iterator_tagboost::detail::input_output_iterator_tag47 operator std::output_iterator_tag() const 48 { 49 return std::output_iterator_tag(); 50 } 51 }; 52 53 // 54 // True iff the user has explicitly disabled writability of this 55 // iterator. Pass the iterator_facade's Value parameter and its 56 // nested ::reference type. 57 // 58 template <class ValueParam, class Reference> 59 struct iterator_writability_disabled 60 # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic? 61 : mpl::or_< 62 is_const<Reference> 63 , boost::detail::indirect_traits::is_reference_to_const<Reference> 64 , is_const<ValueParam> 65 > 66 # else 67 : is_const<ValueParam> 68 # endif 69 {}; 70 71 72 // 73 // Convert an iterator_facade's traversal category, Value parameter, 74 // and ::reference type to an appropriate old-style category. 75 // 76 // If writability has been disabled per the above metafunction, the 77 // result will not be convertible to output_iterator_tag. 78 // 79 // Otherwise, if Traversal == single_pass_traversal_tag, the following 80 // conditions will result in a tag that is convertible both to 81 // input_iterator_tag and output_iterator_tag: 82 // 83 // 1. Reference is a reference to non-const 84 // 2. Reference is not a reference and is convertible to Value 85 // 86 template <class Traversal, class ValueParam, class Reference> 87 struct iterator_facade_default_category 88 : mpl::eval_if< 89 mpl::and_< 90 is_reference<Reference> 91 , is_convertible<Traversal,forward_traversal_tag> 92 > 93 , mpl::eval_if< 94 is_convertible<Traversal,random_access_traversal_tag> 95 , mpl::identity<std::random_access_iterator_tag> 96 , mpl::if_< 97 is_convertible<Traversal,bidirectional_traversal_tag> 98 , std::bidirectional_iterator_tag 99 , std::forward_iterator_tag 100 > 101 > 102 , typename mpl::eval_if< 103 mpl::and_< 104 is_convertible<Traversal, single_pass_traversal_tag> 105 106 // check for readability 107 , is_convertible<Reference, ValueParam> 108 > 109 , mpl::identity<std::input_iterator_tag> 110 , mpl::identity<Traversal> 111 > 112 > 113 { 114 }; 115 116 // True iff T is convertible to an old-style iterator category. 117 template <class T> 118 struct is_iterator_category 119 : mpl::or_< 120 is_convertible<T,std::input_iterator_tag> 121 , is_convertible<T,std::output_iterator_tag> 122 > 123 { 124 }; 125 126 template <class T> 127 struct is_iterator_traversal 128 : is_convertible<T,incrementable_traversal_tag> 129 {}; 130 131 // 132 // A composite iterator_category tag convertible to Category (a pure 133 // old-style category) and Traversal (a pure traversal tag). 134 // Traversal must be a strict increase of the traversal power given by 135 // Category. 136 // 137 template <class Category, class Traversal> 138 struct iterator_category_with_traversal 139 : Category, Traversal 140 { 141 # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) 142 // Make sure this isn't used to build any categories where 143 // convertibility to Traversal is redundant. Should just use the 144 // Category element in that case. 145 BOOST_MPL_ASSERT_NOT(( 146 is_convertible< 147 typename iterator_category_to_traversal<Category>::type 148 , Traversal 149 >)); 150 151 BOOST_MPL_ASSERT((is_iterator_category<Category>)); 152 BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>)); 153 BOOST_MPL_ASSERT_NOT((is_iterator_traversal<Category>)); 154 # if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) 155 BOOST_MPL_ASSERT((is_iterator_traversal<Traversal>)); 156 # endif 157 # endif 158 }; 159 160 // Computes an iterator_category tag whose traversal is Traversal and 161 // which is appropriate for an iterator 162 template <class Traversal, class ValueParam, class Reference> 163 struct facade_iterator_category_impl 164 { 165 # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) 166 BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>)); 167 # endif 168 169 typedef typename iterator_facade_default_category< 170 Traversal,ValueParam,Reference 171 >::type category; 172 173 typedef typename mpl::if_< 174 is_same< 175 Traversal 176 , typename iterator_category_to_traversal<category>::type 177 > 178 , category 179 , iterator_category_with_traversal<category,Traversal> 180 >::type type; 181 }; 182 183 // 184 // Compute an iterator_category for iterator_facade 185 // 186 template <class CategoryOrTraversal, class ValueParam, class Reference> 187 struct facade_iterator_category 188 : mpl::eval_if< 189 is_iterator_category<CategoryOrTraversal> 190 , mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is 191 , facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference> 192 > 193 { 194 }; 195 196 }} // namespace boost::detail 197 198 # include <boost/iterator/detail/config_undef.hpp> 199 200 #endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP 201