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