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