| 1 | // Safe iterator implementation -*- C++ -*- |
|---|
| 2 | |
|---|
| 3 | // Copyright (C) 2003, 2004 |
|---|
| 4 | // Free Software Foundation, Inc. |
|---|
| 5 | // |
|---|
| 6 | // This file is part of the GNU ISO C++ Library. This library is free |
|---|
| 7 | // software; you can redistribute it and/or modify it under the |
|---|
| 8 | // terms of the GNU General Public License as published by the |
|---|
| 9 | // Free Software Foundation; either version 2, or (at your option) |
|---|
| 10 | // any later version. |
|---|
| 11 | |
|---|
| 12 | // This library is distributed in the hope that it will be useful, |
|---|
| 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | // GNU General Public License for more details. |
|---|
| 16 | |
|---|
| 17 | // You should have received a copy of the GNU General Public License along |
|---|
| 18 | // with this library; see the file COPYING. If not, write to the Free |
|---|
| 19 | // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
|---|
| 20 | // USA. |
|---|
| 21 | |
|---|
| 22 | // As a special exception, you may use this file as part of a free software |
|---|
| 23 | // library without restriction. Specifically, if other files instantiate |
|---|
| 24 | // templates or use macros or inline functions from this file, or you compile |
|---|
| 25 | // this file and link it with other files to produce an executable, this |
|---|
| 26 | // file does not by itself cause the resulting executable to be covered by |
|---|
| 27 | // the GNU General Public License. This exception does not however |
|---|
| 28 | // invalidate any other reasons why the executable file might be covered by |
|---|
| 29 | // the GNU General Public License. |
|---|
| 30 | |
|---|
| 31 | #ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H |
|---|
| 32 | #define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1 |
|---|
| 33 | |
|---|
| 34 | #include <bits/stl_pair.h> |
|---|
| 35 | #include <debug/debug.h> |
|---|
| 36 | #include <debug/formatter.h> |
|---|
| 37 | #include <debug/safe_base.h> |
|---|
| 38 | #include <bits/cpp_type_traits.h> |
|---|
| 39 | |
|---|
| 40 | namespace __gnu_debug |
|---|
| 41 | { |
|---|
| 42 | using std::iterator_traits; |
|---|
| 43 | using std::pair; |
|---|
| 44 | |
|---|
| 45 | /** Iterators that derive from _Safe_iterator_base but that aren't |
|---|
| 46 | * _Safe_iterators can be determined singular or non-singular via |
|---|
| 47 | * _Safe_iterator_base. |
|---|
| 48 | */ |
|---|
| 49 | inline bool __check_singular_aux(const _Safe_iterator_base* __x) |
|---|
| 50 | { return __x->_M_singular(); } |
|---|
| 51 | |
|---|
| 52 | /** \brief Safe iterator wrapper. |
|---|
| 53 | * |
|---|
| 54 | * The class template %_Safe_iterator is a wrapper around an |
|---|
| 55 | * iterator that tracks the iterator's movement among sequences and |
|---|
| 56 | * checks that operations performed on the "safe" iterator are |
|---|
| 57 | * legal. In additional to the basic iterator operations (which are |
|---|
| 58 | * validated, and then passed to the underlying iterator), |
|---|
| 59 | * %_Safe_iterator has member functions for iterator invalidation, |
|---|
| 60 | * attaching/detaching the iterator from sequences, and querying |
|---|
| 61 | * the iterator's state. |
|---|
| 62 | */ |
|---|
| 63 | template<typename _Iterator, typename _Sequence> |
|---|
| 64 | class _Safe_iterator : public _Safe_iterator_base |
|---|
| 65 | { |
|---|
| 66 | typedef _Safe_iterator _Self; |
|---|
| 67 | |
|---|
| 68 | /** The precision to which we can calculate the distance between |
|---|
| 69 | * two iterators. |
|---|
| 70 | */ |
|---|
| 71 | enum _Distance_precision |
|---|
| 72 | { |
|---|
| 73 | __dp_equality, //< Can compare iterator equality, only |
|---|
| 74 | __dp_sign, //< Can determine equality and ordering |
|---|
| 75 | __dp_exact //< Can determine distance precisely |
|---|
| 76 | }; |
|---|
| 77 | |
|---|
| 78 | /// The underlying iterator |
|---|
| 79 | _Iterator _M_current; |
|---|
| 80 | |
|---|
| 81 | /// Determine if this is a constant iterator. |
|---|
| 82 | bool |
|---|
| 83 | _M_constant() const |
|---|
| 84 | { |
|---|
| 85 | typedef typename _Sequence::const_iterator const_iterator; |
|---|
| 86 | return __is_same<const_iterator, _Safe_iterator>::value; |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | typedef iterator_traits<_Iterator> _Traits; |
|---|
| 90 | |
|---|
| 91 | public: |
|---|
| 92 | typedef _Iterator _Base_iterator; |
|---|
| 93 | typedef typename _Traits::iterator_category iterator_category; |
|---|
| 94 | typedef typename _Traits::value_type value_type; |
|---|
| 95 | typedef typename _Traits::difference_type difference_type; |
|---|
| 96 | typedef typename _Traits::reference reference; |
|---|
| 97 | typedef typename _Traits::pointer pointer; |
|---|
| 98 | |
|---|
| 99 | /// @post the iterator is singular and unattached |
|---|
| 100 | _Safe_iterator() : _M_current() { } |
|---|
| 101 | |
|---|
| 102 | /** |
|---|
| 103 | * @brief Safe iterator construction from an unsafe iterator and |
|---|
| 104 | * its sequence. |
|---|
| 105 | * |
|---|
| 106 | * @pre @p seq is not NULL |
|---|
| 107 | * @post this is not singular |
|---|
| 108 | */ |
|---|
| 109 | _Safe_iterator(const _Iterator& __i, const _Sequence* __seq) |
|---|
| 110 | : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i) |
|---|
| 111 | { |
|---|
| 112 | _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(), |
|---|
| 113 | _M_message(__msg_init_singular) |
|---|
| 114 | ._M_iterator(*this, "this")); |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | /** |
|---|
| 118 | * @brief Copy construction. |
|---|
| 119 | * @pre @p x is not singular |
|---|
| 120 | */ |
|---|
| 121 | _Safe_iterator(const _Safe_iterator& __x) |
|---|
| 122 | : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current) |
|---|
| 123 | { |
|---|
| 124 | _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(), |
|---|
| 125 | _M_message(__msg_init_copy_singular) |
|---|
| 126 | ._M_iterator(*this, "this") |
|---|
| 127 | ._M_iterator(__x, "other")); |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | /** |
|---|
| 131 | * @brief Converting constructor from a mutable iterator to a |
|---|
| 132 | * constant iterator. |
|---|
| 133 | * |
|---|
| 134 | * @pre @p x is not singular |
|---|
| 135 | */ |
|---|
| 136 | template<typename _MutableIterator> |
|---|
| 137 | _Safe_iterator( |
|---|
| 138 | const _Safe_iterator<_MutableIterator, |
|---|
| 139 | typename std::__enable_if< |
|---|
| 140 | _Sequence, |
|---|
| 141 | (std::__are_same<_MutableIterator, |
|---|
| 142 | typename _Sequence::iterator::_Base_iterator>::_M_type) |
|---|
| 143 | >::_M_type>& __x) |
|---|
| 144 | : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base()) |
|---|
| 145 | { |
|---|
| 146 | _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(), |
|---|
| 147 | _M_message(__msg_init_const_singular) |
|---|
| 148 | ._M_iterator(*this, "this") |
|---|
| 149 | ._M_iterator(__x, "other")); |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | /** |
|---|
| 153 | * @brief Copy assignment. |
|---|
| 154 | * @pre @p x is not singular |
|---|
| 155 | */ |
|---|
| 156 | _Safe_iterator& |
|---|
| 157 | operator=(const _Safe_iterator& __x) |
|---|
| 158 | { |
|---|
| 159 | _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(), |
|---|
| 160 | _M_message(__msg_copy_singular) |
|---|
| 161 | ._M_iterator(*this, "this") |
|---|
| 162 | ._M_iterator(__x, "other")); |
|---|
| 163 | _M_current = __x._M_current; |
|---|
| 164 | this->_M_attach(static_cast<_Sequence*>(__x._M_sequence)); |
|---|
| 165 | return *this; |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | /** |
|---|
| 169 | * @brief Iterator dereference. |
|---|
| 170 | * @pre iterator is dereferenceable |
|---|
| 171 | */ |
|---|
| 172 | reference |
|---|
| 173 | operator*() const |
|---|
| 174 | { |
|---|
| 175 | |
|---|
| 176 | _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), |
|---|
| 177 | _M_message(__msg_bad_deref) |
|---|
| 178 | ._M_iterator(*this, "this")); |
|---|
| 179 | return *_M_current; |
|---|
| 180 | } |
|---|
| 181 | |
|---|
| 182 | /** |
|---|
| 183 | * @brief Iterator dereference. |
|---|
| 184 | * @pre iterator is dereferenceable |
|---|
| 185 | * @todo Make this correct w.r.t. iterators that return proxies |
|---|
| 186 | * @todo Use addressof() instead of & operator |
|---|
| 187 | */ |
|---|
| 188 | pointer |
|---|
| 189 | operator->() const |
|---|
| 190 | { |
|---|
| 191 | _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), |
|---|
| 192 | _M_message(__msg_bad_deref) |
|---|
| 193 | ._M_iterator(*this, "this")); |
|---|
| 194 | return &*_M_current; |
|---|
| 195 | } |
|---|
| 196 | |
|---|
| 197 | // ------ Input iterator requirements ------ |
|---|
| 198 | /** |
|---|
| 199 | * @brief Iterator preincrement |
|---|
| 200 | * @pre iterator is incrementable |
|---|
| 201 | */ |
|---|
| 202 | _Safe_iterator& |
|---|
| 203 | operator++() |
|---|
| 204 | { |
|---|
| 205 | _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), |
|---|
| 206 | _M_message(__msg_bad_inc) |
|---|
| 207 | ._M_iterator(*this, "this")); |
|---|
| 208 | ++_M_current; |
|---|
| 209 | return *this; |
|---|
| 210 | } |
|---|
| 211 | |
|---|
| 212 | /** |
|---|
| 213 | * @brief Iterator postincrement |
|---|
| 214 | * @pre iterator is incrementable |
|---|
| 215 | */ |
|---|
| 216 | _Safe_iterator |
|---|
| 217 | operator++(int) |
|---|
| 218 | { |
|---|
| 219 | _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), |
|---|
| 220 | _M_message(__msg_bad_inc) |
|---|
| 221 | ._M_iterator(*this, "this")); |
|---|
| 222 | _Safe_iterator __tmp(*this); |
|---|
| 223 | ++_M_current; |
|---|
| 224 | return __tmp; |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | // ------ Bidirectional iterator requirements ------ |
|---|
| 228 | /** |
|---|
| 229 | * @brief Iterator predecrement |
|---|
| 230 | * @pre iterator is decrementable |
|---|
| 231 | */ |
|---|
| 232 | _Safe_iterator& |
|---|
| 233 | operator--() |
|---|
| 234 | { |
|---|
| 235 | _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), |
|---|
| 236 | _M_message(__msg_bad_dec) |
|---|
| 237 | ._M_iterator(*this, "this")); |
|---|
| 238 | --_M_current; |
|---|
| 239 | return *this; |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | /** |
|---|
| 243 | * @brief Iterator postdecrement |
|---|
| 244 | * @pre iterator is decrementable |
|---|
| 245 | */ |
|---|
| 246 | _Safe_iterator |
|---|
| 247 | operator--(int) |
|---|
| 248 | { |
|---|
| 249 | _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), |
|---|
| 250 | _M_message(__msg_bad_dec) |
|---|
| 251 | ._M_iterator(*this, "this")); |
|---|
| 252 | _Safe_iterator __tmp(*this); |
|---|
| 253 | --_M_current; |
|---|
| 254 | return __tmp; |
|---|
| 255 | } |
|---|
| 256 | |
|---|
| 257 | // ------ Random access iterator requirements ------ |
|---|
| 258 | reference |
|---|
| 259 | operator[](const difference_type& __n) const |
|---|
| 260 | { |
|---|
| 261 | _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) |
|---|
| 262 | && this->_M_can_advance(__n+1), |
|---|
| 263 | _M_message(__msg_iter_subscript_oob) |
|---|
| 264 | ._M_iterator(*this)._M_integer(__n)); |
|---|
| 265 | |
|---|
| 266 | return _M_current[__n]; |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | _Safe_iterator& |
|---|
| 270 | operator+=(const difference_type& __n) |
|---|
| 271 | { |
|---|
| 272 | _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), |
|---|
| 273 | _M_message(__msg_advance_oob) |
|---|
| 274 | ._M_iterator(*this)._M_integer(__n)); |
|---|
| 275 | _M_current += __n; |
|---|
| 276 | return *this; |
|---|
| 277 | } |
|---|
| 278 | |
|---|
| 279 | _Safe_iterator |
|---|
| 280 | operator+(const difference_type& __n) const |
|---|
| 281 | { |
|---|
| 282 | _Safe_iterator __tmp(*this); |
|---|
| 283 | __tmp += __n; |
|---|
| 284 | return __tmp; |
|---|
| 285 | } |
|---|
| 286 | |
|---|
| 287 | _Safe_iterator& |
|---|
| 288 | operator-=(const difference_type& __n) |
|---|
| 289 | { |
|---|
| 290 | _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), |
|---|
| 291 | _M_message(__msg_retreat_oob) |
|---|
| 292 | ._M_iterator(*this)._M_integer(__n)); |
|---|
| 293 | _M_current += -__n; |
|---|
| 294 | return *this; |
|---|
| 295 | } |
|---|
| 296 | |
|---|
| 297 | _Safe_iterator |
|---|
| 298 | operator-(const difference_type& __n) const |
|---|
| 299 | { |
|---|
| 300 | _Safe_iterator __tmp(*this); |
|---|
| 301 | __tmp -= __n; |
|---|
| 302 | return __tmp; |
|---|
| 303 | } |
|---|
| 304 | |
|---|
| 305 | // ------ Utilities ------ |
|---|
| 306 | /** |
|---|
| 307 | * @brief Return the underlying iterator |
|---|
| 308 | */ |
|---|
| 309 | _Iterator |
|---|
| 310 | base() const { return _M_current; } |
|---|
| 311 | |
|---|
| 312 | /** |
|---|
| 313 | * @brief Conversion to underlying non-debug iterator to allow |
|---|
| 314 | * better interaction with non-debug containers. |
|---|
| 315 | */ |
|---|
| 316 | operator _Iterator() const { return _M_current; } |
|---|
| 317 | |
|---|
| 318 | /** Attach iterator to the given sequence. */ |
|---|
| 319 | void |
|---|
| 320 | _M_attach(const _Sequence* __seq) |
|---|
| 321 | { |
|---|
| 322 | _Safe_iterator_base::_M_attach(const_cast<_Sequence*>(__seq), |
|---|
| 323 | _M_constant()); |
|---|
| 324 | } |
|---|
| 325 | |
|---|
| 326 | /** Invalidate the iterator, making it singular. */ |
|---|
| 327 | void |
|---|
| 328 | _M_invalidate(); |
|---|
| 329 | |
|---|
| 330 | /// Is the iterator dereferenceable? |
|---|
| 331 | bool |
|---|
| 332 | _M_dereferenceable() const |
|---|
| 333 | { return !this->_M_singular() && !_M_is_end(); } |
|---|
| 334 | |
|---|
| 335 | /// Is the iterator incrementable? |
|---|
| 336 | bool |
|---|
| 337 | _M_incrementable() const { return this->_M_dereferenceable(); } |
|---|
| 338 | |
|---|
| 339 | // Is the iterator decrementable? |
|---|
| 340 | bool |
|---|
| 341 | _M_decrementable() const { return !_M_singular() && !_M_is_begin(); } |
|---|
| 342 | |
|---|
| 343 | // Can we advance the iterator @p __n steps (@p __n may be negative) |
|---|
| 344 | bool |
|---|
| 345 | _M_can_advance(const difference_type& __n) const; |
|---|
| 346 | |
|---|
| 347 | // Is the iterator range [*this, __rhs) valid? |
|---|
| 348 | template<typename _Other> |
|---|
| 349 | bool |
|---|
| 350 | _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const; |
|---|
| 351 | |
|---|
| 352 | // The sequence this iterator references. |
|---|
| 353 | const _Sequence* |
|---|
| 354 | _M_get_sequence() const |
|---|
| 355 | { return static_cast<const _Sequence*>(_M_sequence); } |
|---|
| 356 | |
|---|
| 357 | /** Determine the distance between two iterators with some known |
|---|
| 358 | * precision. |
|---|
| 359 | */ |
|---|
| 360 | template<typename _Iterator1, typename _Iterator2> |
|---|
| 361 | static pair<difference_type, _Distance_precision> |
|---|
| 362 | _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs) |
|---|
| 363 | { |
|---|
| 364 | typedef typename iterator_traits<_Iterator1>::iterator_category |
|---|
| 365 | _Category; |
|---|
| 366 | return _M_get_distance(__lhs, __rhs, _Category()); |
|---|
| 367 | } |
|---|
| 368 | |
|---|
| 369 | template<typename _Iterator1, typename _Iterator2> |
|---|
| 370 | static pair<difference_type, _Distance_precision> |
|---|
| 371 | _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs, |
|---|
| 372 | std::random_access_iterator_tag) |
|---|
| 373 | { |
|---|
| 374 | return std::make_pair(__rhs.base() - __lhs.base(), __dp_exact); |
|---|
| 375 | } |
|---|
| 376 | |
|---|
| 377 | template<typename _Iterator1, typename _Iterator2> |
|---|
| 378 | static pair<difference_type, _Distance_precision> |
|---|
| 379 | _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs, |
|---|
| 380 | std::forward_iterator_tag) |
|---|
| 381 | { |
|---|
| 382 | return std::make_pair(__lhs.base() == __rhs.base()? 0 : 1, |
|---|
| 383 | __dp_equality); |
|---|
| 384 | } |
|---|
| 385 | |
|---|
| 386 | /// Is this iterator equal to the sequence's begin() iterator? |
|---|
| 387 | bool _M_is_begin() const |
|---|
| 388 | { return *this == static_cast<const _Sequence*>(_M_sequence)->begin(); } |
|---|
| 389 | |
|---|
| 390 | /// Is this iterator equal to the sequence's end() iterator? |
|---|
| 391 | bool _M_is_end() const |
|---|
| 392 | { return *this == static_cast<const _Sequence*>(_M_sequence)->end(); } |
|---|
| 393 | }; |
|---|
| 394 | |
|---|
| 395 | template<typename _IteratorL, typename _IteratorR, typename _Sequence> |
|---|
| 396 | inline bool |
|---|
| 397 | operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, |
|---|
| 398 | const _Safe_iterator<_IteratorR, _Sequence>& __rhs) |
|---|
| 399 | { |
|---|
| 400 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 401 | _M_message(__msg_iter_compare_bad) |
|---|
| 402 | ._M_iterator(__lhs, "lhs") |
|---|
| 403 | ._M_iterator(__rhs, "rhs")); |
|---|
| 404 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 405 | _M_message(__msg_compare_different) |
|---|
| 406 | ._M_iterator(__lhs, "lhs") |
|---|
| 407 | ._M_iterator(__rhs, "rhs")); |
|---|
| 408 | return __lhs.base() == __rhs.base(); |
|---|
| 409 | } |
|---|
| 410 | |
|---|
| 411 | template<typename _Iterator, typename _Sequence> |
|---|
| 412 | inline bool |
|---|
| 413 | operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs, |
|---|
| 414 | const _Safe_iterator<_Iterator, _Sequence>& __rhs) |
|---|
| 415 | { |
|---|
| 416 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 417 | _M_message(__msg_iter_compare_bad) |
|---|
| 418 | ._M_iterator(__lhs, "lhs") |
|---|
| 419 | ._M_iterator(__rhs, "rhs")); |
|---|
| 420 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 421 | _M_message(__msg_compare_different) |
|---|
| 422 | ._M_iterator(__lhs, "lhs") |
|---|
| 423 | ._M_iterator(__rhs, "rhs")); |
|---|
| 424 | return __lhs.base() == __rhs.base(); |
|---|
| 425 | } |
|---|
| 426 | |
|---|
| 427 | template<typename _IteratorL, typename _IteratorR, typename _Sequence> |
|---|
| 428 | inline bool |
|---|
| 429 | operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, |
|---|
| 430 | const _Safe_iterator<_IteratorR, _Sequence>& __rhs) |
|---|
| 431 | { |
|---|
| 432 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 433 | _M_message(__msg_iter_compare_bad) |
|---|
| 434 | ._M_iterator(__lhs, "lhs") |
|---|
| 435 | ._M_iterator(__rhs, "rhs")); |
|---|
| 436 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 437 | _M_message(__msg_compare_different) |
|---|
| 438 | ._M_iterator(__lhs, "lhs") |
|---|
| 439 | ._M_iterator(__rhs, "rhs")); |
|---|
| 440 | return __lhs.base() != __rhs.base(); |
|---|
| 441 | } |
|---|
| 442 | |
|---|
| 443 | template<typename _Iterator, typename _Sequence> |
|---|
| 444 | inline bool |
|---|
| 445 | operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, |
|---|
| 446 | const _Safe_iterator<_Iterator, _Sequence>& __rhs) |
|---|
| 447 | { |
|---|
| 448 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 449 | _M_message(__msg_iter_compare_bad) |
|---|
| 450 | ._M_iterator(__lhs, "lhs") |
|---|
| 451 | ._M_iterator(__rhs, "rhs")); |
|---|
| 452 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 453 | _M_message(__msg_compare_different) |
|---|
| 454 | ._M_iterator(__lhs, "lhs") |
|---|
| 455 | ._M_iterator(__rhs, "rhs")); |
|---|
| 456 | return __lhs.base() != __rhs.base(); |
|---|
| 457 | } |
|---|
| 458 | |
|---|
| 459 | template<typename _IteratorL, typename _IteratorR, typename _Sequence> |
|---|
| 460 | inline bool |
|---|
| 461 | operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, |
|---|
| 462 | const _Safe_iterator<_IteratorR, _Sequence>& __rhs) |
|---|
| 463 | { |
|---|
| 464 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 465 | _M_message(__msg_iter_order_bad) |
|---|
| 466 | ._M_iterator(__lhs, "lhs") |
|---|
| 467 | ._M_iterator(__rhs, "rhs")); |
|---|
| 468 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 469 | _M_message(__msg_order_different) |
|---|
| 470 | ._M_iterator(__lhs, "lhs") |
|---|
| 471 | ._M_iterator(__rhs, "rhs")); |
|---|
| 472 | return __lhs.base() < __rhs.base(); |
|---|
| 473 | } |
|---|
| 474 | |
|---|
| 475 | template<typename _Iterator, typename _Sequence> |
|---|
| 476 | inline bool |
|---|
| 477 | operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs, |
|---|
| 478 | const _Safe_iterator<_Iterator, _Sequence>& __rhs) |
|---|
| 479 | { |
|---|
| 480 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 481 | _M_message(__msg_iter_order_bad) |
|---|
| 482 | ._M_iterator(__lhs, "lhs") |
|---|
| 483 | ._M_iterator(__rhs, "rhs")); |
|---|
| 484 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 485 | _M_message(__msg_order_different) |
|---|
| 486 | ._M_iterator(__lhs, "lhs") |
|---|
| 487 | ._M_iterator(__rhs, "rhs")); |
|---|
| 488 | return __lhs.base() < __rhs.base(); |
|---|
| 489 | } |
|---|
| 490 | |
|---|
| 491 | template<typename _IteratorL, typename _IteratorR, typename _Sequence> |
|---|
| 492 | inline bool |
|---|
| 493 | operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, |
|---|
| 494 | const _Safe_iterator<_IteratorR, _Sequence>& __rhs) |
|---|
| 495 | { |
|---|
| 496 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 497 | _M_message(__msg_iter_order_bad) |
|---|
| 498 | ._M_iterator(__lhs, "lhs") |
|---|
| 499 | ._M_iterator(__rhs, "rhs")); |
|---|
| 500 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 501 | _M_message(__msg_order_different) |
|---|
| 502 | ._M_iterator(__lhs, "lhs") |
|---|
| 503 | ._M_iterator(__rhs, "rhs")); |
|---|
| 504 | return __lhs.base() <= __rhs.base(); |
|---|
| 505 | } |
|---|
| 506 | |
|---|
| 507 | template<typename _Iterator, typename _Sequence> |
|---|
| 508 | inline bool |
|---|
| 509 | operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, |
|---|
| 510 | const _Safe_iterator<_Iterator, _Sequence>& __rhs) |
|---|
| 511 | { |
|---|
| 512 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 513 | _M_message(__msg_iter_order_bad) |
|---|
| 514 | ._M_iterator(__lhs, "lhs") |
|---|
| 515 | ._M_iterator(__rhs, "rhs")); |
|---|
| 516 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 517 | _M_message(__msg_order_different) |
|---|
| 518 | ._M_iterator(__lhs, "lhs") |
|---|
| 519 | ._M_iterator(__rhs, "rhs")); |
|---|
| 520 | return __lhs.base() <= __rhs.base(); |
|---|
| 521 | } |
|---|
| 522 | |
|---|
| 523 | template<typename _IteratorL, typename _IteratorR, typename _Sequence> |
|---|
| 524 | inline bool |
|---|
| 525 | operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, |
|---|
| 526 | const _Safe_iterator<_IteratorR, _Sequence>& __rhs) |
|---|
| 527 | { |
|---|
| 528 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 529 | _M_message(__msg_iter_order_bad) |
|---|
| 530 | ._M_iterator(__lhs, "lhs") |
|---|
| 531 | ._M_iterator(__rhs, "rhs")); |
|---|
| 532 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 533 | _M_message(__msg_order_different) |
|---|
| 534 | ._M_iterator(__lhs, "lhs") |
|---|
| 535 | ._M_iterator(__rhs, "rhs")); |
|---|
| 536 | return __lhs.base() > __rhs.base(); |
|---|
| 537 | } |
|---|
| 538 | |
|---|
| 539 | template<typename _Iterator, typename _Sequence> |
|---|
| 540 | inline bool |
|---|
| 541 | operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs, |
|---|
| 542 | const _Safe_iterator<_Iterator, _Sequence>& __rhs) |
|---|
| 543 | { |
|---|
| 544 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 545 | _M_message(__msg_iter_order_bad) |
|---|
| 546 | ._M_iterator(__lhs, "lhs") |
|---|
| 547 | ._M_iterator(__rhs, "rhs")); |
|---|
| 548 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 549 | _M_message(__msg_order_different) |
|---|
| 550 | ._M_iterator(__lhs, "lhs") |
|---|
| 551 | ._M_iterator(__rhs, "rhs")); |
|---|
| 552 | return __lhs.base() > __rhs.base(); |
|---|
| 553 | } |
|---|
| 554 | |
|---|
| 555 | template<typename _IteratorL, typename _IteratorR, typename _Sequence> |
|---|
| 556 | inline bool |
|---|
| 557 | operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, |
|---|
| 558 | const _Safe_iterator<_IteratorR, _Sequence>& __rhs) |
|---|
| 559 | { |
|---|
| 560 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 561 | _M_message(__msg_iter_order_bad) |
|---|
| 562 | ._M_iterator(__lhs, "lhs") |
|---|
| 563 | ._M_iterator(__rhs, "rhs")); |
|---|
| 564 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 565 | _M_message(__msg_order_different) |
|---|
| 566 | ._M_iterator(__lhs, "lhs") |
|---|
| 567 | ._M_iterator(__rhs, "rhs")); |
|---|
| 568 | return __lhs.base() >= __rhs.base(); |
|---|
| 569 | } |
|---|
| 570 | |
|---|
| 571 | template<typename _Iterator, typename _Sequence> |
|---|
| 572 | inline bool |
|---|
| 573 | operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, |
|---|
| 574 | const _Safe_iterator<_Iterator, _Sequence>& __rhs) |
|---|
| 575 | { |
|---|
| 576 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 577 | _M_message(__msg_iter_order_bad) |
|---|
| 578 | ._M_iterator(__lhs, "lhs") |
|---|
| 579 | ._M_iterator(__rhs, "rhs")); |
|---|
| 580 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 581 | _M_message(__msg_order_different) |
|---|
| 582 | ._M_iterator(__lhs, "lhs") |
|---|
| 583 | ._M_iterator(__rhs, "rhs")); |
|---|
| 584 | return __lhs.base() >= __rhs.base(); |
|---|
| 585 | } |
|---|
| 586 | |
|---|
| 587 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
|---|
| 588 | // According to the resolution of DR179 not only the various comparison |
|---|
| 589 | // operators but also operator- must accept mixed iterator/const_iterator |
|---|
| 590 | // parameters. |
|---|
| 591 | template<typename _IteratorL, typename _IteratorR, typename _Sequence> |
|---|
| 592 | inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type |
|---|
| 593 | operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, |
|---|
| 594 | const _Safe_iterator<_IteratorR, _Sequence>& __rhs) |
|---|
| 595 | { |
|---|
| 596 | _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), |
|---|
| 597 | _M_message(__msg_distance_bad) |
|---|
| 598 | ._M_iterator(__lhs, "lhs") |
|---|
| 599 | ._M_iterator(__rhs, "rhs")); |
|---|
| 600 | _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), |
|---|
| 601 | _M_message(__msg_distance_different) |
|---|
| 602 | ._M_iterator(__lhs, "lhs") |
|---|
| 603 | ._M_iterator(__rhs, "rhs")); |
|---|
| 604 | return __lhs.base() - __rhs.base(); |
|---|
| 605 | } |
|---|
| 606 | |
|---|
| 607 | template<typename _Iterator, typename _Sequence> |
|---|
| 608 | inline _Safe_iterator<_Iterator, _Sequence> |
|---|
| 609 | operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n, |
|---|
| 610 | const _Safe_iterator<_Iterator, _Sequence>& __i) |
|---|
| 611 | { return __i + __n; } |
|---|
| 612 | } // namespace __gnu_debug |
|---|
| 613 | |
|---|
| 614 | #ifndef _GLIBCXX_EXPORT_TEMPLATE |
|---|
| 615 | # include <debug/safe_iterator.tcc> |
|---|
| 616 | #endif |
|---|
| 617 | |
|---|
| 618 | #endif |
|---|