1 // (C) Copyright David Abrahams 2002. 2 // (C) Copyright Jeremy Siek 2002. 3 // (C) Copyright Thomas Witt 2002. 4 // Distributed under the Boost Software License, Version 1.0. (See 5 // accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 #ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP 8 #define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP 9 10 #include <boost/static_assert.hpp> 11 #include <boost/iterator.hpp> 12 #include <boost/detail/iterator.hpp> 13 14 #include <boost/iterator/iterator_categories.hpp> 15 #include <boost/iterator/iterator_facade.hpp> 16 #include <boost/iterator/detail/enable_if.hpp> 17 18 #include <boost/mpl/and.hpp> 19 #include <boost/mpl/not.hpp> 20 #include <boost/mpl/or.hpp> 21 22 #include <boost/type_traits/is_same.hpp> 23 #include <boost/type_traits/is_convertible.hpp> 24 25 #ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 26 # include <boost/type_traits/remove_reference.hpp> 27 #endif 28 29 #include <boost/type_traits/add_reference.hpp> 30 #include <boost/iterator/detail/config_def.hpp> 31 32 #include <boost/iterator/iterator_traits.hpp> 33 34 namespace boost { 35 namespace iterators { 36 37 // Used as a default template argument internally, merely to 38 // indicate "use the default", this can also be passed by users 39 // explicitly in order to specify that the default should be used. 40 struct use_default; 41 42 } // namespace iterators 43 44 using iterators::use_default; 45 46 // the incompleteness of use_default causes massive problems for 47 // is_convertible (naturally). This workaround is fortunately not 48 // needed for vc6/vc7. 49 template<class To> 50 struct is_convertible<use_default,To> 51 : mpl::false_ {}; 52 53 namespace iterators { 54 55 namespace detail 56 { 57 58 // 59 // Result type used in enable_if_convertible meta function. 60 // This can be an incomplete type, as only pointers to 61 // enable_if_convertible< ... >::type are used. 62 // We could have used void for this, but conversion to 63 // void* is just to easy. 64 // 65 struct enable_type; 66 } 67 68 69 // 70 // enable_if for use in adapted iterators constructors. 71 // 72 // In order to provide interoperability between adapted constant and 73 // mutable iterators, adapted iterators will usually provide templated 74 // conversion constructors of the following form 75 // 76 // template <class BaseIterator> 77 // class adapted_iterator : 78 // public iterator_adaptor< adapted_iterator<Iterator>, Iterator > 79 // { 80 // public: 81 // 82 // ... 83 // 84 // template <class OtherIterator> 85 // adapted_iterator( 86 // OtherIterator const& it 87 // , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0); 88 // 89 // ... 90 // }; 91 // 92 // enable_if_convertible is used to remove those overloads from the overload 93 // set that cannot be instantiated. For all practical purposes only overloads 94 // for constant/mutable interaction will remain. This has the advantage that 95 // meta functions like boost::is_convertible do not return false positives, 96 // as they can only look at the signature of the conversion constructor 97 // and not at the actual instantiation. 98 // 99 // enable_if_interoperable can be safely used in user code. It falls back to 100 // always enabled for compilers that don't support enable_if or is_convertible. 101 // There is no need for compiler specific workarounds in user code. 102 // 103 // The operators implementation relies on boost::is_convertible not returning 104 // false positives for user/library defined iterator types. See comments 105 // on operator implementation for consequences. 106 // 107 # if defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE) 108 109 template <class From, class To> 110 struct enable_if_convertible 111 { 112 typedef boost::iterators::detail::enable_type type; 113 }; 114 115 # elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) 116 117 // For some reason vc7.1 needs us to "cut off" instantiation 118 // of is_convertible in a few cases. 119 template<typename From, typename To> 120 struct enable_if_convertible 121 : iterators::enable_if< 122 mpl::or_< 123 is_same<From,To> 124 , is_convertible<From, To> 125 > 126 , boost::iterators::detail::enable_type 127 > 128 {}; 129 130 # else 131 132 template<typename From, typename To> 133 struct enable_if_convertible 134 : iterators::enable_if< 135 is_convertible<From, To> 136 , boost::iterators::detail::enable_type 137 > 138 {}; 139 140 # endif 141 142 // 143 // Default template argument handling for iterator_adaptor 144 // 145 namespace detail 146 { 147 // If T is use_default, return the result of invoking 148 // DefaultNullaryFn, otherwise return T. 149 template <class T, class DefaultNullaryFn> 150 struct ia_dflt_help 151 : mpl::eval_if< 152 is_same<T, use_default> 153 , DefaultNullaryFn 154 , mpl::identity<T> 155 > 156 { 157 }; 158 159 // A metafunction which computes an iterator_adaptor's base class, 160 // a specialization of iterator_facade. 161 template < 162 class Derived 163 , class Base 164 , class Value 165 , class Traversal 166 , class Reference 167 , class Difference 168 > 169 struct iterator_adaptor_base 170 { 171 typedef iterator_facade< 172 Derived 173 174 # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 175 , typename boost::iterators::detail::ia_dflt_help< 176 Value 177 , mpl::eval_if< 178 is_same<Reference,use_default> 179 , iterator_value<Base> 180 , remove_reference<Reference> 181 > 182 >::type 183 # else 184 , typename boost::iterators::detail::ia_dflt_help< 185 Value, iterator_value<Base> 186 >::type 187 # endif 188 189 , typename boost::iterators::detail::ia_dflt_help< 190 Traversal 191 , iterator_traversal<Base> 192 >::type 193 194 , typename boost::iterators::detail::ia_dflt_help< 195 Reference 196 , mpl::eval_if< 197 is_same<Value,use_default> 198 , iterator_reference<Base> 199 , add_reference<Value> 200 > 201 >::type 202 203 , typename boost::iterators::detail::ia_dflt_help< 204 Difference, iterator_difference<Base> 205 >::type 206 > 207 type; 208 }; 209 210 // workaround for aC++ CR JAGaf33512 211 template <class Tr1, class Tr2> iterator_adaptor_assert_traversal()212 inline void iterator_adaptor_assert_traversal () 213 { 214 BOOST_STATIC_ASSERT((is_convertible<Tr1, Tr2>::value)); 215 } 216 } 217 218 // 219 // Iterator Adaptor 220 // 221 // The parameter ordering changed slightly with respect to former 222 // versions of iterator_adaptor The idea is that when the user needs 223 // to fiddle with the reference type it is highly likely that the 224 // iterator category has to be adjusted as well. Any of the 225 // following four template arguments may be ommitted or explicitly 226 // replaced by use_default. 227 // 228 // Value - if supplied, the value_type of the resulting iterator, unless 229 // const. If const, a conforming compiler strips constness for the 230 // value_type. If not supplied, iterator_traits<Base>::value_type is used 231 // 232 // Category - the traversal category of the resulting iterator. If not 233 // supplied, iterator_traversal<Base>::type is used. 234 // 235 // Reference - the reference type of the resulting iterator, and in 236 // particular, the result type of operator*(). If not supplied but 237 // Value is supplied, Value& is used. Otherwise 238 // iterator_traits<Base>::reference is used. 239 // 240 // Difference - the difference_type of the resulting iterator. If not 241 // supplied, iterator_traits<Base>::difference_type is used. 242 // 243 template < 244 class Derived 245 , class Base 246 , class Value = use_default 247 , class Traversal = use_default 248 , class Reference = use_default 249 , class Difference = use_default 250 > 251 class iterator_adaptor 252 : public boost::iterators::detail::iterator_adaptor_base< 253 Derived, Base, Value, Traversal, Reference, Difference 254 >::type 255 { 256 friend class iterator_core_access; 257 258 protected: 259 typedef typename boost::iterators::detail::iterator_adaptor_base< 260 Derived, Base, Value, Traversal, Reference, Difference 261 >::type super_t; 262 public: iterator_adaptor()263 iterator_adaptor() {} 264 iterator_adaptor(Base const & iter)265 explicit iterator_adaptor(Base const &iter) 266 : m_iterator(iter) 267 { 268 } 269 270 typedef Base base_type; 271 base() const272 Base const& base() const 273 { return m_iterator; } 274 275 protected: 276 // for convenience in derived classes 277 typedef iterator_adaptor<Derived,Base,Value,Traversal,Reference,Difference> iterator_adaptor_; 278 279 // 280 // lvalue access to the Base object for Derived 281 // base_reference() const282 Base const& base_reference() const 283 { return m_iterator; } 284 base_reference()285 Base& base_reference() 286 { return m_iterator; } 287 288 private: 289 // 290 // Core iterator interface for iterator_facade. This is private 291 // to prevent temptation for Derived classes to use it, which 292 // will often result in an error. Derived classes should use 293 // base_reference(), above, to get direct access to m_iterator. 294 // dereference() const295 typename super_t::reference dereference() const 296 { return *m_iterator; } 297 298 template < 299 class OtherDerived, class OtherIterator, class V, class C, class R, class D 300 > equal(iterator_adaptor<OtherDerived,OtherIterator,V,C,R,D> const & x) const301 bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const 302 { 303 // Maybe readd with same_distance 304 // BOOST_STATIC_ASSERT( 305 // (detail::same_category_and_difference<Derived,OtherDerived>::value) 306 // ); 307 return m_iterator == x.base(); 308 } 309 310 typedef typename iterator_category_to_traversal< 311 typename super_t::iterator_category 312 >::type my_traversal; 313 314 # define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \ 315 boost::iterators::detail::iterator_adaptor_assert_traversal<my_traversal, cat>(); 316 advance(typename super_t::difference_type n)317 void advance(typename super_t::difference_type n) 318 { 319 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) 320 m_iterator += n; 321 } 322 increment()323 void increment() { ++m_iterator; } 324 decrement()325 void decrement() 326 { 327 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag) 328 --m_iterator; 329 } 330 331 template < 332 class OtherDerived, class OtherIterator, class V, class C, class R, class D 333 > distance_to(iterator_adaptor<OtherDerived,OtherIterator,V,C,R,D> const & y) const334 typename super_t::difference_type distance_to( 335 iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const 336 { 337 BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) 338 // Maybe readd with same_distance 339 // BOOST_STATIC_ASSERT( 340 // (detail::same_category_and_difference<Derived,OtherDerived>::value) 341 // ); 342 return y.base() - m_iterator; 343 } 344 345 # undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL 346 347 private: // data members 348 Base m_iterator; 349 }; 350 351 } // namespace iterators 352 353 using iterators::iterator_adaptor; 354 using iterators::enable_if_convertible; 355 356 } // namespace boost 357 358 #include <boost/iterator/detail/config_undef.hpp> 359 360 #endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP 361