Home | History | Annotate | Download | only in debug
      1 // Debugging list implementation -*- C++ -*-
      2 
      3 // Copyright (C) 2003-2013 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file debug/list
     26  *  This file is a GNU debug extension to the Standard C++ Library.
     27  */
     28 
     29 #ifndef _GLIBCXX_DEBUG_LIST
     30 #define _GLIBCXX_DEBUG_LIST 1
     31 
     32 #include <list>
     33 #include <debug/safe_sequence.h>
     34 #include <debug/safe_iterator.h>
     35 
     36 namespace std _GLIBCXX_VISIBILITY(default)
     37 {
     38 namespace __debug
     39 {
     40   /// Class std::list with safety/checking/debug instrumentation.
     41   template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
     42     class list
     43     : public _GLIBCXX_STD_C::list<_Tp, _Allocator>,
     44       public __gnu_debug::_Safe_sequence<list<_Tp, _Allocator> >
     45     {
     46       typedef _GLIBCXX_STD_C::list<_Tp, _Allocator> _Base;
     47 
     48       typedef typename _Base::iterator       _Base_iterator;
     49       typedef typename _Base::const_iterator _Base_const_iterator;
     50       typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
     51       typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal;
     52     public:
     53       typedef typename _Base::reference             reference;
     54       typedef typename _Base::const_reference       const_reference;
     55 
     56       typedef __gnu_debug::_Safe_iterator<_Base_iterator, list>
     57 						    iterator;
     58       typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, list>
     59 						    const_iterator;
     60 
     61       typedef typename _Base::size_type             size_type;
     62       typedef typename _Base::difference_type       difference_type;
     63 
     64       typedef _Tp				    value_type;
     65       typedef _Allocator			    allocator_type;
     66       typedef typename _Base::pointer               pointer;
     67       typedef typename _Base::const_pointer         const_pointer;
     68       typedef std::reverse_iterator<iterator>       reverse_iterator;
     69       typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
     70 
     71       // 23.2.2.1 construct/copy/destroy:
     72       explicit
     73       list(const _Allocator& __a = _Allocator())
     74       : _Base(__a) { }
     75 
     76 #if __cplusplus >= 201103L
     77       explicit
     78       list(size_type __n)
     79       : _Base(__n) { }
     80 
     81       list(size_type __n, const _Tp& __value,
     82 	   const _Allocator& __a = _Allocator())
     83       : _Base(__n, __value, __a) { }
     84 #else
     85       explicit
     86       list(size_type __n, const _Tp& __value = _Tp(),
     87 	   const _Allocator& __a = _Allocator())
     88       : _Base(__n, __value, __a) { }
     89 #endif
     90 
     91 #if __cplusplus >= 201103L
     92       template<class _InputIterator,
     93 	       typename = std::_RequireInputIter<_InputIterator>>
     94 #else
     95       template<class _InputIterator>
     96 #endif
     97 	list(_InputIterator __first, _InputIterator __last,
     98 	     const _Allocator& __a = _Allocator())
     99 	: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
    100 								     __last)),
    101 		__gnu_debug::__base(__last), __a)
    102         { }
    103 
    104       list(const list& __x)
    105       : _Base(__x) { }
    106 
    107       list(const _Base& __x)
    108       : _Base(__x) { }
    109 
    110 #if __cplusplus >= 201103L
    111       list(list&& __x) noexcept
    112       : _Base(std::move(__x))
    113       { this->_M_swap(__x); }
    114 
    115       list(initializer_list<value_type> __l,
    116            const allocator_type& __a = allocator_type())
    117         : _Base(__l, __a) { }
    118 #endif
    119 
    120       ~list() _GLIBCXX_NOEXCEPT { }
    121 
    122       list&
    123       operator=(const list& __x)
    124       {
    125 	static_cast<_Base&>(*this) = __x;
    126 	this->_M_invalidate_all();
    127 	return *this;
    128       }
    129 
    130 #if __cplusplus >= 201103L
    131       list&
    132       operator=(list&& __x)
    133       {
    134 	// NB: DR 1204.
    135 	// NB: DR 675.
    136 	__glibcxx_check_self_move_assign(__x);
    137 	clear();
    138 	swap(__x);
    139       	return *this;
    140       }
    141 
    142       list&
    143       operator=(initializer_list<value_type> __l)
    144       {
    145 	static_cast<_Base&>(*this) = __l;
    146 	this->_M_invalidate_all();
    147 	return *this;
    148       }
    149 
    150       void
    151       assign(initializer_list<value_type> __l)
    152       {
    153 	_Base::assign(__l);
    154 	this->_M_invalidate_all();
    155       }
    156 #endif
    157 
    158 #if __cplusplus >= 201103L
    159       template<class _InputIterator,
    160 	       typename = std::_RequireInputIter<_InputIterator>>
    161 #else
    162       template<class _InputIterator>
    163 #endif
    164         void
    165         assign(_InputIterator __first, _InputIterator __last)
    166         {
    167 	  __glibcxx_check_valid_range(__first, __last);
    168 	  _Base::assign(__gnu_debug::__base(__first),
    169 			__gnu_debug::__base(__last));
    170 	  this->_M_invalidate_all();
    171 	}
    172 
    173       void
    174       assign(size_type __n, const _Tp& __t)
    175       {
    176 	_Base::assign(__n, __t);
    177 	this->_M_invalidate_all();
    178       }
    179 
    180       using _Base::get_allocator;
    181 
    182       // iterators:
    183       iterator
    184       begin() _GLIBCXX_NOEXCEPT
    185       { return iterator(_Base::begin(), this); }
    186 
    187       const_iterator
    188       begin() const _GLIBCXX_NOEXCEPT
    189       { return const_iterator(_Base::begin(), this); }
    190 
    191       iterator
    192       end() _GLIBCXX_NOEXCEPT
    193       { return iterator(_Base::end(), this); }
    194 
    195       const_iterator
    196       end() const _GLIBCXX_NOEXCEPT
    197       { return const_iterator(_Base::end(), this); }
    198 
    199       reverse_iterator
    200       rbegin() _GLIBCXX_NOEXCEPT
    201       { return reverse_iterator(end()); }
    202 
    203       const_reverse_iterator
    204       rbegin() const _GLIBCXX_NOEXCEPT
    205       { return const_reverse_iterator(end()); }
    206 
    207       reverse_iterator
    208       rend() _GLIBCXX_NOEXCEPT
    209       { return reverse_iterator(begin()); }
    210 
    211       const_reverse_iterator
    212       rend() const _GLIBCXX_NOEXCEPT
    213       { return const_reverse_iterator(begin()); }
    214 
    215 #if __cplusplus >= 201103L
    216       const_iterator
    217       cbegin() const noexcept
    218       { return const_iterator(_Base::begin(), this); }
    219 
    220       const_iterator
    221       cend() const noexcept
    222       { return const_iterator(_Base::end(), this); }
    223 
    224       const_reverse_iterator
    225       crbegin() const noexcept
    226       { return const_reverse_iterator(end()); }
    227 
    228       const_reverse_iterator
    229       crend() const noexcept
    230       { return const_reverse_iterator(begin()); }
    231 #endif
    232 
    233       // 23.2.2.2 capacity:
    234       using _Base::empty;
    235       using _Base::size;
    236       using _Base::max_size;
    237 
    238 #if __cplusplus >= 201103L
    239       void
    240       resize(size_type __sz)
    241       {
    242 	this->_M_detach_singular();
    243 
    244 	// if __sz < size(), invalidate all iterators in [begin+__sz, end())
    245 	_Base_iterator __victim = _Base::begin();
    246 	_Base_iterator __end = _Base::end();
    247 	for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
    248 	  ++__victim;
    249 
    250 	for (; __victim != __end; ++__victim)
    251 	  {
    252 	    this->_M_invalidate_if(_Equal(__victim));
    253 	  }
    254 
    255 	__try
    256 	  {
    257 	    _Base::resize(__sz);
    258 	  }
    259 	__catch(...)
    260 	  {
    261 	    this->_M_revalidate_singular();
    262 	    __throw_exception_again;
    263 	  }
    264       }
    265 
    266       void
    267       resize(size_type __sz, const _Tp& __c)
    268       {
    269 	this->_M_detach_singular();
    270 
    271 	// if __sz < size(), invalidate all iterators in [begin+__sz, end())
    272 	_Base_iterator __victim = _Base::begin();
    273 	_Base_iterator __end = _Base::end();
    274 	for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
    275 	  ++__victim;
    276 
    277 	for (; __victim != __end; ++__victim)
    278 	  {
    279 	    this->_M_invalidate_if(_Equal(__victim));
    280 	  }
    281 
    282 	__try
    283 	  {
    284 	    _Base::resize(__sz, __c);
    285 	  }
    286 	__catch(...)
    287 	  {
    288 	    this->_M_revalidate_singular();
    289 	    __throw_exception_again;
    290 	  }
    291       }
    292 #else
    293       void
    294       resize(size_type __sz, _Tp __c = _Tp())
    295       {
    296 	this->_M_detach_singular();
    297 
    298 	// if __sz < size(), invalidate all iterators in [begin+__sz, end())
    299 	_Base_iterator __victim = _Base::begin();
    300 	_Base_iterator __end = _Base::end();
    301 	for (size_type __i = __sz; __victim != __end && __i > 0; --__i)
    302 	  ++__victim;
    303 
    304 	for (; __victim != __end; ++__victim)
    305 	  {
    306 	    this->_M_invalidate_if(_Equal(__victim));
    307 	  }
    308 
    309 	__try
    310 	  {
    311 	    _Base::resize(__sz, __c);
    312 	  }
    313 	__catch(...)
    314 	  {
    315 	    this->_M_revalidate_singular();
    316 	    __throw_exception_again;
    317 	  }
    318       }
    319 #endif
    320 
    321       // element access:
    322       reference
    323       front()
    324       {
    325 	__glibcxx_check_nonempty();
    326 	return _Base::front();
    327       }
    328 
    329       const_reference
    330       front() const
    331       {
    332 	__glibcxx_check_nonempty();
    333 	return _Base::front();
    334       }
    335 
    336       reference
    337       back()
    338       {
    339 	__glibcxx_check_nonempty();
    340 	return _Base::back();
    341       }
    342 
    343       const_reference
    344       back() const
    345       {
    346 	__glibcxx_check_nonempty();
    347 	return _Base::back();
    348       }
    349 
    350       // 23.2.2.3 modifiers:
    351       using _Base::push_front;
    352 
    353 #if __cplusplus >= 201103L
    354       using _Base::emplace_front;
    355 #endif
    356 
    357       void
    358       pop_front()
    359       {
    360 	__glibcxx_check_nonempty();
    361 	this->_M_invalidate_if(_Equal(_Base::begin()));
    362 	_Base::pop_front();
    363       }
    364 
    365       using _Base::push_back;
    366 
    367 #if __cplusplus >= 201103L
    368       using _Base::emplace_back;
    369 #endif
    370 
    371       void
    372       pop_back()
    373       {
    374 	__glibcxx_check_nonempty();
    375 	this->_M_invalidate_if(_Equal(--_Base::end()));
    376 	_Base::pop_back();
    377       }
    378 
    379 #if __cplusplus >= 201103L
    380       template<typename... _Args>
    381         iterator
    382         emplace(iterator __position, _Args&&... __args)
    383 	{
    384 	  __glibcxx_check_insert(__position);
    385 	  return iterator(_Base::emplace(__position.base(),
    386 					std::forward<_Args>(__args)...), this);
    387 	}
    388 #endif
    389 
    390       iterator
    391       insert(iterator __position, const _Tp& __x)
    392       {
    393 	__glibcxx_check_insert(__position);
    394 	return iterator(_Base::insert(__position.base(), __x), this);
    395       }
    396 
    397 #if __cplusplus >= 201103L
    398       iterator
    399       insert(iterator __position, _Tp&& __x)
    400       { return emplace(__position, std::move(__x)); }
    401 
    402       void
    403       insert(iterator __p, initializer_list<value_type> __l)
    404       {
    405 	__glibcxx_check_insert(__p);
    406 	_Base::insert(__p.base(), __l);
    407       }
    408 #endif
    409 
    410       void
    411       insert(iterator __position, size_type __n, const _Tp& __x)
    412       {
    413 	__glibcxx_check_insert(__position);
    414 	_Base::insert(__position.base(), __n, __x);
    415       }
    416 
    417 #if __cplusplus >= 201103L
    418       template<class _InputIterator,
    419 	       typename = std::_RequireInputIter<_InputIterator>>
    420 #else
    421       template<class _InputIterator>
    422 #endif
    423         void
    424         insert(iterator __position, _InputIterator __first,
    425 	       _InputIterator __last)
    426         {
    427 	  __glibcxx_check_insert_range(__position, __first, __last);
    428 	  _Base::insert(__position.base(), __gnu_debug::__base(__first),
    429 					   __gnu_debug::__base(__last));
    430 	}
    431 
    432     private:
    433       _Base_iterator
    434       _M_erase(_Base_iterator __position)
    435       {
    436 	this->_M_invalidate_if(_Equal(__position));
    437 	return _Base::erase(__position);
    438       }
    439     public:
    440       iterator
    441       erase(iterator __position)
    442       {
    443 	__glibcxx_check_erase(__position);
    444 	return iterator(_M_erase(__position.base()), this);
    445       }
    446 
    447       iterator
    448       erase(iterator __position, iterator __last)
    449       {
    450 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
    451 	// 151. can't currently clear() empty container
    452 	__glibcxx_check_erase_range(__position, __last);
    453 	for (_Base_iterator __victim = __position.base();
    454 	     __victim != __last.base(); ++__victim)
    455 	  {
    456 	    _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
    457 			          _M_message(__gnu_debug::__msg_valid_range)
    458 				  ._M_iterator(__position, "position")
    459 				  ._M_iterator(__last, "last"));
    460 	    this->_M_invalidate_if(_Equal(__victim));
    461 	  }
    462 	return iterator(_Base::erase(__position.base(), __last.base()), this);
    463       }
    464 
    465       void
    466       swap(list& __x)
    467       {
    468 	_Base::swap(__x);
    469 	this->_M_swap(__x);
    470       }
    471 
    472       void
    473       clear() _GLIBCXX_NOEXCEPT
    474       {
    475 	_Base::clear();
    476 	this->_M_invalidate_all();
    477       }
    478 
    479       // 23.2.2.4 list operations:
    480       void
    481 #if __cplusplus >= 201103L
    482       splice(iterator __position, list&& __x)
    483 #else
    484       splice(iterator __position, list& __x)
    485 #endif
    486       {
    487 	_GLIBCXX_DEBUG_VERIFY(&__x != this,
    488 			      _M_message(__gnu_debug::__msg_self_splice)
    489 			      ._M_sequence(*this, "this"));
    490 	this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end()));
    491 	_Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()));
    492       }
    493 
    494 #if __cplusplus >= 201103L
    495       void
    496       splice(iterator __position, list& __x)
    497       { splice(__position, std::move(__x)); }
    498 #endif
    499 
    500       void
    501 #if __cplusplus >= 201103L
    502       splice(iterator __position, list&& __x, iterator __i)
    503 #else
    504       splice(iterator __position, list& __x, iterator __i)
    505 #endif
    506       {
    507 	__glibcxx_check_insert(__position);
    508 
    509 	// We used to perform the splice_alloc check:  not anymore, redundant
    510 	// after implementing the relevant bits of N1599.
    511 
    512 	_GLIBCXX_DEBUG_VERIFY(__i._M_dereferenceable(),
    513 			      _M_message(__gnu_debug::__msg_splice_bad)
    514 			      ._M_iterator(__i, "__i"));
    515 	_GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__x),
    516 			      _M_message(__gnu_debug::__msg_splice_other)
    517 			     ._M_iterator(__i, "__i")._M_sequence(__x, "__x"));
    518 
    519 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
    520 	// 250. splicing invalidates iterators
    521 	this->_M_transfer_from_if(__x, _Equal(__i.base()));
    522 	_Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
    523 		      __i.base());
    524       }
    525 
    526 #if __cplusplus >= 201103L
    527       void
    528       splice(iterator __position, list& __x, iterator __i)
    529       { splice(__position, std::move(__x), __i); }
    530 #endif
    531 
    532       void
    533 #if __cplusplus >= 201103L
    534       splice(iterator __position, list&& __x, iterator __first,
    535 	     iterator __last)
    536 #else
    537       splice(iterator __position, list& __x, iterator __first,
    538 	     iterator __last)
    539 #endif
    540       {
    541 	__glibcxx_check_insert(__position);
    542 	__glibcxx_check_valid_range(__first, __last);
    543 	_GLIBCXX_DEBUG_VERIFY(__first._M_attached_to(&__x),
    544 			      _M_message(__gnu_debug::__msg_splice_other)
    545 			      ._M_sequence(__x, "x")
    546 			      ._M_iterator(__first, "first"));
    547 
    548 	// We used to perform the splice_alloc check:  not anymore, redundant
    549 	// after implementing the relevant bits of N1599.
    550 
    551 	for (_Base_iterator __tmp = __first.base();
    552 	     __tmp != __last.base(); ++__tmp)
    553 	  {
    554 	    _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
    555 				  _M_message(__gnu_debug::__msg_valid_range)
    556 				  ._M_iterator(__first, "first")
    557 				  ._M_iterator(__last, "last"));
    558 	    _GLIBCXX_DEBUG_VERIFY(&__x != this || __tmp != __position,
    559 				_M_message(__gnu_debug::__msg_splice_overlap)
    560 				  ._M_iterator(__tmp, "position")
    561 				  ._M_iterator(__first, "first")
    562 				  ._M_iterator(__last, "last"));
    563 	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    564 	    // 250. splicing invalidates iterators
    565 	    this->_M_transfer_from_if(__x, _Equal(__tmp));
    566 	  }
    567 
    568 	_Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()),
    569 		      __first.base(), __last.base());
    570       }
    571 
    572 #if __cplusplus >= 201103L
    573       void
    574       splice(iterator __position, list& __x, iterator __first, iterator __last)
    575       { splice(__position, std::move(__x), __first, __last); }
    576 #endif
    577 
    578       void
    579       remove(const _Tp& __value)
    580       {
    581 	for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); )
    582 	  {
    583 	    if (*__x == __value)
    584 	      __x = _M_erase(__x);
    585 	    else
    586 	      ++__x;
    587 	  }
    588       }
    589 
    590       template<class _Predicate>
    591         void
    592         remove_if(_Predicate __pred)
    593         {
    594 	  for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); )
    595 	    {
    596 	      if (__pred(*__x))
    597 		__x = _M_erase(__x);
    598 	      else
    599 		++__x;
    600 	    }
    601 	}
    602 
    603       void
    604       unique()
    605       {
    606 	_Base_iterator __first = _Base::begin();
    607 	_Base_iterator __last = _Base::end();
    608 	if (__first == __last)
    609 	  return;
    610 	_Base_iterator __next = __first; ++__next;
    611 	while (__next != __last)
    612 	  {
    613 	    if (*__first == *__next)
    614 	      __next = _M_erase(__next);
    615 	    else
    616 	      __first = __next++;
    617 	  }
    618       }
    619 
    620       template<class _BinaryPredicate>
    621         void
    622         unique(_BinaryPredicate __binary_pred)
    623         {
    624 	  _Base_iterator __first = _Base::begin();
    625 	  _Base_iterator __last = _Base::end();
    626 	  if (__first == __last)
    627 	    return;
    628 	  _Base_iterator __next = __first; ++__next;
    629 	  while (__next != __last)
    630 	    {
    631 	      if (__binary_pred(*__first, *__next))
    632 		__next = _M_erase(__next);
    633 	      else
    634 		__first = __next++;
    635 	    }
    636 	}
    637 
    638       void
    639 #if __cplusplus >= 201103L
    640       merge(list&& __x)
    641 #else
    642       merge(list& __x)
    643 #endif
    644       {
    645 	// _GLIBCXX_RESOLVE_LIB_DEFECTS
    646 	// 300. list::merge() specification incomplete
    647 	if (this != &__x)
    648 	  {
    649 	    __glibcxx_check_sorted(_Base::begin(), _Base::end());
    650 	    __glibcxx_check_sorted(__x.begin().base(), __x.end().base());
    651 	    this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end()));
    652 	    _Base::merge(_GLIBCXX_MOVE(__x._M_base()));
    653 	  }
    654       }
    655 
    656 #if __cplusplus >= 201103L
    657       void
    658       merge(list& __x)
    659       { merge(std::move(__x)); }
    660 #endif
    661 
    662       template<class _Compare>
    663         void
    664 #if __cplusplus >= 201103L
    665         merge(list&& __x, _Compare __comp)
    666 #else
    667         merge(list& __x, _Compare __comp)
    668 #endif
    669         {
    670 	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
    671 	  // 300. list::merge() specification incomplete
    672 	  if (this != &__x)
    673 	    {
    674 	      __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(),
    675 					  __comp);
    676 	      __glibcxx_check_sorted_pred(__x.begin().base(), __x.end().base(),
    677 					  __comp);
    678 	      this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end()));
    679 	      _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp);
    680 	    }
    681 	}
    682 
    683 #if __cplusplus >= 201103L
    684       template<typename _Compare>
    685         void
    686         merge(list& __x, _Compare __comp)
    687         { merge(std::move(__x), __comp); }
    688 #endif
    689 
    690       void
    691       sort() { _Base::sort(); }
    692 
    693       template<typename _StrictWeakOrdering>
    694         void
    695         sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); }
    696 
    697       using _Base::reverse;
    698 
    699       _Base&
    700       _M_base() _GLIBCXX_NOEXCEPT       { return *this; }
    701 
    702       const _Base&
    703       _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
    704 
    705     private:
    706       void
    707       _M_invalidate_all()
    708       {
    709 	this->_M_invalidate_if(_Not_equal(_Base::end()));
    710       }
    711     };
    712 
    713   template<typename _Tp, typename _Alloc>
    714     inline bool
    715     operator==(const list<_Tp, _Alloc>& __lhs,
    716 	       const list<_Tp, _Alloc>& __rhs)
    717     { return __lhs._M_base() == __rhs._M_base(); }
    718 
    719   template<typename _Tp, typename _Alloc>
    720     inline bool
    721     operator!=(const list<_Tp, _Alloc>& __lhs,
    722 	       const list<_Tp, _Alloc>& __rhs)
    723     { return __lhs._M_base() != __rhs._M_base(); }
    724 
    725   template<typename _Tp, typename _Alloc>
    726     inline bool
    727     operator<(const list<_Tp, _Alloc>& __lhs,
    728 	      const list<_Tp, _Alloc>& __rhs)
    729     { return __lhs._M_base() < __rhs._M_base(); }
    730 
    731   template<typename _Tp, typename _Alloc>
    732     inline bool
    733     operator<=(const list<_Tp, _Alloc>& __lhs,
    734 	       const list<_Tp, _Alloc>& __rhs)
    735     { return __lhs._M_base() <= __rhs._M_base(); }
    736 
    737   template<typename _Tp, typename _Alloc>
    738     inline bool
    739     operator>=(const list<_Tp, _Alloc>& __lhs,
    740 	       const list<_Tp, _Alloc>& __rhs)
    741     { return __lhs._M_base() >= __rhs._M_base(); }
    742 
    743   template<typename _Tp, typename _Alloc>
    744     inline bool
    745     operator>(const list<_Tp, _Alloc>& __lhs,
    746 	      const list<_Tp, _Alloc>& __rhs)
    747     { return __lhs._M_base() > __rhs._M_base(); }
    748 
    749   template<typename _Tp, typename _Alloc>
    750     inline void
    751     swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs)
    752     { __lhs.swap(__rhs); }
    753 
    754 } // namespace __debug
    755 } // namespace std
    756 
    757 #endif
    758