(root)/
gcc-13.2.0/
libstdc++-v3/
include/
debug/
multimap.h
       1  // Debugging multimap implementation -*- C++ -*-
       2  
       3  // Copyright (C) 2003-2023 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/multimap.h
      26   *  This file is a GNU debug extension to the Standard C++ Library.
      27   */
      28  
      29  #ifndef _GLIBCXX_DEBUG_MULTIMAP_H
      30  #define _GLIBCXX_DEBUG_MULTIMAP_H 1
      31  
      32  #include <debug/safe_sequence.h>
      33  #include <debug/safe_container.h>
      34  #include <debug/safe_iterator.h>
      35  #include <bits/stl_pair.h>
      36  
      37  namespace std _GLIBCXX_VISIBILITY(default)
      38  {
      39  namespace __debug
      40  {
      41    /// Class std::multimap with safety/checking/debug instrumentation.
      42    template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
      43  	   typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
      44      class multimap
      45        : public __gnu_debug::_Safe_container<
      46  	multimap<_Key, _Tp, _Compare, _Allocator>, _Allocator,
      47  	__gnu_debug::_Safe_node_sequence>,
      48  	public _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator>
      49      {
      50        typedef _GLIBCXX_STD_C::multimap<
      51  	_Key, _Tp, _Compare, _Allocator>			_Base;
      52        typedef __gnu_debug::_Safe_container<
      53  	multimap, _Allocator, __gnu_debug::_Safe_node_sequence>	_Safe;
      54  
      55        typedef typename _Base::const_iterator	_Base_const_iterator;
      56        typedef typename _Base::iterator		_Base_iterator;
      57        typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal;
      58  
      59        template<typename _ItT, typename _SeqT, typename _CatT>
      60  	friend class ::__gnu_debug::_Safe_iterator;
      61  
      62        // Reference wrapper for base class. Disambiguates multimap(const _Base&)
      63        // from copy constructor by requiring a user-defined conversion.
      64        // See PR libstdc++/90102.
      65        struct _Base_ref
      66        {
      67  	_Base_ref(const _Base& __r) : _M_ref(__r) { }
      68  
      69  	const _Base& _M_ref;
      70        };
      71  
      72      public:
      73        // types:
      74        typedef _Key					key_type;
      75        typedef _Tp					mapped_type;
      76        typedef std::pair<const _Key, _Tp>		value_type;
      77        typedef _Compare					key_compare;
      78        typedef _Allocator				allocator_type;
      79        typedef typename _Base::reference			reference;
      80        typedef typename _Base::const_reference		const_reference;
      81  
      82        typedef __gnu_debug::_Safe_iterator<_Base_iterator, multimap>
      83  							iterator;
      84        typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
      85  					  multimap>	const_iterator;
      86  
      87        typedef typename _Base::size_type			size_type;
      88        typedef typename _Base::difference_type		difference_type;
      89        typedef typename _Base::pointer			pointer;
      90        typedef typename _Base::const_pointer		const_pointer;
      91        typedef std::reverse_iterator<iterator>		reverse_iterator;
      92        typedef std::reverse_iterator<const_iterator>	const_reverse_iterator;
      93  
      94        // 23.3.1.1 construct/copy/destroy:
      95  
      96  #if __cplusplus < 201103L
      97        multimap() : _Base() { }
      98  
      99        multimap(const multimap& __x)
     100        : _Base(__x) { }
     101  
     102        ~multimap() { }
     103  #else
     104        multimap() = default;
     105        multimap(const multimap&) = default;
     106        multimap(multimap&&) = default;
     107  
     108        multimap(initializer_list<value_type> __l,
     109  	       const _Compare& __c = _Compare(),
     110  	       const allocator_type& __a = allocator_type())
     111        : _Base(__l, __c, __a) { }
     112  
     113        explicit
     114        multimap(const allocator_type& __a)
     115        : _Base(__a) { }
     116  
     117        multimap(const multimap& __m,
     118  	       const __type_identity_t<allocator_type>& __a)
     119        : _Base(__m, __a) { }
     120  
     121        multimap(multimap&& __m, const __type_identity_t<allocator_type>& __a)
     122        noexcept( noexcept(_Base(std::move(__m), __a)) )
     123        : _Safe(std::move(__m), __a),
     124  	_Base(std::move(__m), __a) { }
     125  
     126        multimap(initializer_list<value_type> __l, const allocator_type& __a)
     127        : _Base(__l, __a) { }
     128  
     129        template<typename _InputIterator>
     130  	multimap(_InputIterator __first, _InputIterator __last,
     131  		 const allocator_type& __a)
     132  	: _Base(__gnu_debug::__base(
     133  		  __glibcxx_check_valid_constructor_range(__first, __last)),
     134  		__gnu_debug::__base(__last), __a) { }
     135  
     136        ~multimap() = default;
     137  #endif
     138  
     139        explicit multimap(const _Compare& __comp,
     140  			const _Allocator& __a = _Allocator())
     141        : _Base(__comp, __a) { }
     142  
     143        template<typename _InputIterator>
     144        multimap(_InputIterator __first, _InputIterator __last,
     145  	       const _Compare& __comp = _Compare(),
     146  	       const _Allocator& __a = _Allocator())
     147  	: _Base(__gnu_debug::__base(
     148  		  __glibcxx_check_valid_constructor_range(__first, __last)),
     149  		__gnu_debug::__base(__last),
     150  	      __comp, __a) { }
     151  
     152        multimap(_Base_ref __x)
     153        : _Base(__x._M_ref) { }
     154  
     155  #if __cplusplus >= 201103L
     156        multimap&
     157        operator=(const multimap&) = default;
     158  
     159        multimap&
     160        operator=(multimap&&) = default;
     161  
     162        multimap&
     163        operator=(initializer_list<value_type> __l)
     164        {
     165  	_Base::operator=(__l);
     166  	this->_M_invalidate_all();
     167  	return *this;
     168        }
     169  #endif
     170  
     171        using _Base::get_allocator;
     172  
     173        // iterators:
     174        iterator
     175        begin() _GLIBCXX_NOEXCEPT
     176        { return iterator(_Base::begin(), this); }
     177  
     178        const_iterator
     179        begin() const _GLIBCXX_NOEXCEPT
     180        { return const_iterator(_Base::begin(), this); }
     181  
     182        iterator
     183        end() _GLIBCXX_NOEXCEPT
     184        { return iterator(_Base::end(), this); }
     185  
     186        const_iterator
     187        end() const _GLIBCXX_NOEXCEPT
     188        { return const_iterator(_Base::end(), this); }
     189  
     190        reverse_iterator
     191        rbegin() _GLIBCXX_NOEXCEPT
     192        { return reverse_iterator(end()); }
     193  
     194        const_reverse_iterator
     195        rbegin() const _GLIBCXX_NOEXCEPT
     196        { return const_reverse_iterator(end()); }
     197  
     198        reverse_iterator
     199        rend() _GLIBCXX_NOEXCEPT
     200        { return reverse_iterator(begin()); }
     201  
     202        const_reverse_iterator
     203        rend() const _GLIBCXX_NOEXCEPT
     204        { return const_reverse_iterator(begin()); }
     205  
     206  #if __cplusplus >= 201103L
     207        const_iterator
     208        cbegin() const noexcept
     209        { return const_iterator(_Base::begin(), this); }
     210  
     211        const_iterator
     212        cend() const noexcept
     213        { return const_iterator(_Base::end(), this); }
     214  
     215        const_reverse_iterator
     216        crbegin() const noexcept
     217        { return const_reverse_iterator(end()); }
     218  
     219        const_reverse_iterator
     220        crend() const noexcept
     221        { return const_reverse_iterator(begin()); }
     222  #endif
     223  
     224        // capacity:
     225        using _Base::empty;
     226        using _Base::size;
     227        using _Base::max_size;
     228  
     229        // modifiers:
     230  #if __cplusplus >= 201103L
     231        template<typename... _Args>
     232  	iterator
     233  	emplace(_Args&&... __args)
     234  	{ return { _Base::emplace(std::forward<_Args>(__args)...), this }; }
     235  
     236        template<typename... _Args>
     237  	iterator
     238  	emplace_hint(const_iterator __pos, _Args&&... __args)
     239  	{
     240  	  __glibcxx_check_insert(__pos);
     241  	  return
     242  	    {
     243  	      _Base::emplace_hint(__pos.base(), std::forward<_Args>(__args)...),
     244  	      this
     245  	    };
     246  	}
     247  #endif
     248  
     249        iterator
     250        insert(const value_type& __x)
     251        { return iterator(_Base::insert(__x), this); }
     252  
     253  #if __cplusplus >= 201103L
     254        // _GLIBCXX_RESOLVE_LIB_DEFECTS
     255        // 2354. Unnecessary copying when inserting into maps with braced-init
     256        iterator
     257        insert(value_type&& __x)
     258        { return { _Base::insert(std::move(__x)), this }; }
     259  
     260        template<typename _Pair, typename = typename
     261  	       std::enable_if<std::is_constructible<value_type,
     262  						    _Pair&&>::value>::type>
     263  	iterator
     264  	insert(_Pair&& __x)
     265  	{ return { _Base::insert(std::forward<_Pair>(__x)), this }; }
     266  #endif
     267  
     268  #if __cplusplus >= 201103L
     269        void
     270        insert(std::initializer_list<value_type> __list)
     271        { _Base::insert(__list); }
     272  #endif
     273  
     274        iterator
     275  #if __cplusplus >= 201103L
     276        insert(const_iterator __position, const value_type& __x)
     277  #else
     278        insert(iterator __position, const value_type& __x)
     279  #endif
     280        {
     281  	__glibcxx_check_insert(__position);
     282  	return iterator(_Base::insert(__position.base(), __x), this);
     283        }
     284  
     285  #if __cplusplus >= 201103L
     286        // _GLIBCXX_RESOLVE_LIB_DEFECTS
     287        // 2354. Unnecessary copying when inserting into maps with braced-init
     288        iterator
     289        insert(const_iterator __position, value_type&& __x)
     290        {
     291  	__glibcxx_check_insert(__position);
     292  	return { _Base::insert(__position.base(), std::move(__x)), this };
     293        }
     294  
     295        template<typename _Pair, typename = typename
     296  	       std::enable_if<std::is_constructible<value_type,
     297  						    _Pair&&>::value>::type>
     298  	iterator
     299  	insert(const_iterator __position, _Pair&& __x)
     300  	{
     301  	  __glibcxx_check_insert(__position);
     302  	  return
     303  	    {
     304  	      _Base::insert(__position.base(), std::forward<_Pair>(__x)),
     305  	      this
     306  	    };
     307  	}
     308  #endif
     309  
     310        template<typename _InputIterator>
     311  	void
     312  	insert(_InputIterator __first, _InputIterator __last)
     313  	{
     314  	  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
     315  	  __glibcxx_check_valid_range2(__first, __last, __dist);
     316  
     317  	  if (__dist.second >= __gnu_debug::__dp_sign)
     318  	    _Base::insert(__gnu_debug::__unsafe(__first),
     319  			  __gnu_debug::__unsafe(__last));
     320  	  else
     321  	    _Base::insert(__first, __last);
     322  	}
     323  
     324  #if __cplusplus > 201402L
     325        using node_type = typename _Base::node_type;
     326  
     327        node_type
     328        extract(const_iterator __position)
     329        {
     330  	__glibcxx_check_erase(__position);
     331  	this->_M_invalidate_if(_Equal(__position.base()));
     332  	return _Base::extract(__position.base());
     333        }
     334  
     335        node_type
     336        extract(const key_type& __key)
     337        {
     338  	const auto __position = find(__key);
     339  	if (__position != end())
     340  	  return extract(__position);
     341  	return {};
     342        }
     343  
     344        iterator
     345        insert(node_type&& __nh)
     346        { return { _Base::insert(std::move(__nh)), this }; }
     347  
     348        iterator
     349        insert(const_iterator __hint, node_type&& __nh)
     350        {
     351  	__glibcxx_check_insert(__hint);
     352  	return { _Base::insert(__hint.base(), std::move(__nh)), this };
     353        }
     354  
     355        using _Base::merge;
     356  #endif // C++17
     357  
     358  #if __cplusplus >= 201103L
     359        iterator
     360        erase(const_iterator __position)
     361        {
     362  	__glibcxx_check_erase(__position);
     363  	return { erase(__position.base()), this };
     364        }
     365  
     366        _Base_iterator
     367        erase(_Base_const_iterator __position)
     368        {
     369  	__glibcxx_check_erase2(__position);
     370  	this->_M_invalidate_if(_Equal(__position));
     371  	return _Base::erase(__position);
     372        }
     373  
     374        _GLIBCXX_ABI_TAG_CXX11
     375        iterator
     376        erase(iterator __position)
     377        { return erase(const_iterator(__position)); }
     378  #else
     379        void
     380        erase(iterator __position)
     381        {
     382  	__glibcxx_check_erase(__position);
     383  	this->_M_invalidate_if(_Equal(__position.base()));
     384  	_Base::erase(__position.base());
     385        }
     386  #endif
     387  
     388        size_type
     389        erase(const key_type& __x)
     390        {
     391  	std::pair<_Base_iterator, _Base_iterator> __victims =
     392  	  _Base::equal_range(__x);
     393  	size_type __count = 0;
     394  	_Base_iterator __victim = __victims.first;
     395  	while (__victim !=  __victims.second)
     396  	  {
     397  	    this->_M_invalidate_if(_Equal(__victim));
     398  	    _Base::erase(__victim++);
     399  	    ++__count;
     400  	  }
     401  	return __count;
     402        }
     403  
     404  #if __cplusplus >= 201103L
     405        iterator
     406        erase(const_iterator __first, const_iterator __last)
     407        {
     408  	// _GLIBCXX_RESOLVE_LIB_DEFECTS
     409  	// 151. can't currently clear() empty container
     410  	__glibcxx_check_erase_range(__first, __last);
     411  	for (_Base_const_iterator __victim = __first.base();
     412  	     __victim != __last.base(); ++__victim)
     413  	  {
     414  	    _GLIBCXX_DEBUG_VERIFY(__victim != _Base::cend(),
     415  				  _M_message(__gnu_debug::__msg_valid_range)
     416  				  ._M_iterator(__first, "first")
     417  				  ._M_iterator(__last, "last"));
     418  	    this->_M_invalidate_if(_Equal(__victim));
     419  	  }
     420  
     421  	return { _Base::erase(__first.base(), __last.base()), this };
     422        }
     423  #else
     424        void
     425        erase(iterator __first, iterator __last)
     426        {
     427  	// _GLIBCXX_RESOLVE_LIB_DEFECTS
     428  	// 151. can't currently clear() empty container
     429  	__glibcxx_check_erase_range(__first, __last);
     430  	for (_Base_iterator __victim = __first.base();
     431  	     __victim != __last.base(); ++__victim)
     432  	  {
     433  	    _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
     434  				  _M_message(__gnu_debug::__msg_valid_range)
     435  				  ._M_iterator(__first, "first")
     436  				  ._M_iterator(__last, "last"));
     437  	    this->_M_invalidate_if(_Equal(__victim));
     438  	  }
     439  	_Base::erase(__first.base(), __last.base());
     440        }
     441  #endif
     442  
     443        void
     444        swap(multimap& __x)
     445        _GLIBCXX_NOEXCEPT_IF( noexcept(declval<_Base&>().swap(__x)) )
     446        {
     447  	_Safe::_M_swap(__x);
     448  	_Base::swap(__x);
     449        }
     450  
     451        void
     452        clear() _GLIBCXX_NOEXCEPT
     453        {
     454  	this->_M_invalidate_all();
     455  	_Base::clear();
     456        }
     457  
     458        // observers:
     459        using _Base::key_comp;
     460        using _Base::value_comp;
     461  
     462        // 23.3.1.3 multimap operations:
     463        iterator
     464        find(const key_type& __x)
     465        { return iterator(_Base::find(__x), this); }
     466  
     467  #if __cplusplus > 201103L
     468        template<typename _Kt,
     469  	       typename _Req =
     470  		 typename __has_is_transparent<_Compare, _Kt>::type>
     471  	iterator
     472  	find(const _Kt& __x)
     473  	{ return { _Base::find(__x), this }; }
     474  #endif
     475  
     476        const_iterator
     477        find(const key_type& __x) const
     478        { return const_iterator(_Base::find(__x), this); }
     479  
     480  #if __cplusplus > 201103L
     481        template<typename _Kt,
     482  	       typename _Req =
     483  		 typename __has_is_transparent<_Compare, _Kt>::type>
     484  	const_iterator
     485  	find(const _Kt& __x) const
     486  	{ return { _Base::find(__x), this }; }
     487  #endif
     488  
     489        using _Base::count;
     490  
     491        iterator
     492        lower_bound(const key_type& __x)
     493        { return iterator(_Base::lower_bound(__x), this); }
     494  
     495  #if __cplusplus > 201103L
     496        template<typename _Kt,
     497  	       typename _Req =
     498  		 typename __has_is_transparent<_Compare, _Kt>::type>
     499  	iterator
     500  	lower_bound(const _Kt& __x)
     501  	{ return { _Base::lower_bound(__x), this }; }
     502  #endif
     503  
     504        const_iterator
     505        lower_bound(const key_type& __x) const
     506        { return const_iterator(_Base::lower_bound(__x), this); }
     507  
     508  #if __cplusplus > 201103L
     509        template<typename _Kt,
     510  	       typename _Req =
     511  		 typename __has_is_transparent<_Compare, _Kt>::type>
     512  	const_iterator
     513  	lower_bound(const _Kt& __x) const
     514  	{ return { _Base::lower_bound(__x), this }; }
     515  #endif
     516  
     517        iterator
     518        upper_bound(const key_type& __x)
     519        { return iterator(_Base::upper_bound(__x), this); }
     520  
     521  #if __cplusplus > 201103L
     522        template<typename _Kt,
     523  	       typename _Req =
     524  		 typename __has_is_transparent<_Compare, _Kt>::type>
     525  	iterator
     526  	upper_bound(const _Kt& __x)
     527  	{ return { _Base::upper_bound(__x), this }; }
     528  #endif
     529  
     530        const_iterator
     531        upper_bound(const key_type& __x) const
     532        { return const_iterator(_Base::upper_bound(__x), this); }
     533  
     534  #if __cplusplus > 201103L
     535        template<typename _Kt,
     536  	       typename _Req =
     537  		 typename __has_is_transparent<_Compare, _Kt>::type>
     538  	const_iterator
     539  	upper_bound(const _Kt& __x) const
     540  	{ return { _Base::upper_bound(__x), this }; }
     541  #endif
     542  
     543        std::pair<iterator,iterator>
     544        equal_range(const key_type& __x)
     545        {
     546  	std::pair<_Base_iterator, _Base_iterator> __res =
     547  	_Base::equal_range(__x);
     548  	return std::make_pair(iterator(__res.first, this),
     549  			      iterator(__res.second, this));
     550        }
     551  
     552  #if __cplusplus > 201103L
     553        template<typename _Kt,
     554  	       typename _Req =
     555  		 typename __has_is_transparent<_Compare, _Kt>::type>
     556  	std::pair<iterator, iterator>
     557  	equal_range(const _Kt& __x)
     558  	{
     559  	  auto __res = _Base::equal_range(__x);
     560  	  return { { __res.first, this }, { __res.second, this } };
     561  	}
     562  #endif
     563  
     564        std::pair<const_iterator,const_iterator>
     565        equal_range(const key_type& __x) const
     566        {
     567  	std::pair<_Base_const_iterator, _Base_const_iterator> __res =
     568  	  _Base::equal_range(__x);
     569  	return std::make_pair(const_iterator(__res.first, this),
     570  			      const_iterator(__res.second, this));
     571        }
     572  
     573  #if __cplusplus > 201103L
     574        template<typename _Kt,
     575  	       typename _Req =
     576  		 typename __has_is_transparent<_Compare, _Kt>::type>
     577  	std::pair<const_iterator, const_iterator>
     578  	equal_range(const _Kt& __x) const
     579  	{
     580  	  auto __res = _Base::equal_range(__x);
     581  	  return { { __res.first, this }, { __res.second, this } };
     582  	}
     583  #endif
     584  
     585        _Base&
     586        _M_base() _GLIBCXX_NOEXCEPT { return *this; }
     587  
     588        const _Base&
     589        _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
     590      };
     591  
     592  #if __cpp_deduction_guides >= 201606
     593  
     594    template<typename _InputIterator,
     595  	   typename _Compare = less<__iter_key_t<_InputIterator>>,
     596  	   typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>,
     597  	   typename = _RequireInputIter<_InputIterator>,
     598  	   typename = _RequireNotAllocator<_Compare>,
     599  	   typename = _RequireAllocator<_Allocator>>
     600      multimap(_InputIterator, _InputIterator,
     601  	     _Compare = _Compare(), _Allocator = _Allocator())
     602      -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>,
     603  		_Compare, _Allocator>;
     604  
     605    template<typename _Key, typename _Tp, typename _Compare = less<_Key>,
     606  	   typename _Allocator = allocator<pair<const _Key, _Tp>>,
     607  	   typename = _RequireNotAllocator<_Compare>,
     608  	   typename = _RequireAllocator<_Allocator>>
     609      multimap(initializer_list<pair<_Key, _Tp>>,
     610  	     _Compare = _Compare(), _Allocator = _Allocator())
     611      -> multimap<_Key, _Tp, _Compare, _Allocator>;
     612  
     613    template<typename _InputIterator, typename _Allocator,
     614  	   typename = _RequireInputIter<_InputIterator>,
     615  	   typename = _RequireAllocator<_Allocator>>
     616      multimap(_InputIterator, _InputIterator, _Allocator)
     617      -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>,
     618      less<__iter_key_t<_InputIterator>>, _Allocator>;
     619  
     620    template<typename _Key, typename _Tp, typename _Allocator,
     621  	   typename = _RequireAllocator<_Allocator>>
     622      multimap(initializer_list<pair<_Key, _Tp>>, _Allocator)
     623      -> multimap<_Key, _Tp, less<_Key>, _Allocator>;
     624  
     625  #endif
     626  
     627    template<typename _Key, typename _Tp,
     628  	   typename _Compare, typename _Allocator>
     629      inline bool
     630      operator==(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
     631  	       const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
     632      { return __lhs._M_base() == __rhs._M_base(); }
     633  
     634  #if __cpp_lib_three_way_comparison
     635    template<typename _Key, typename _Tp, typename _Compare, typename _Alloc>
     636      inline __detail::__synth3way_t<pair<const _Key, _Tp>>
     637      operator<=>(const multimap<_Key, _Tp, _Compare, _Alloc>& __lhs,
     638  		const multimap<_Key, _Tp, _Compare, _Alloc>& __rhs)
     639      { return __lhs._M_base() <=> __rhs._M_base(); }
     640  #else
     641    template<typename _Key, typename _Tp,
     642  	   typename _Compare, typename _Allocator>
     643      inline bool
     644      operator!=(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
     645  	       const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
     646      { return __lhs._M_base() != __rhs._M_base(); }
     647  
     648    template<typename _Key, typename _Tp,
     649  	   typename _Compare, typename _Allocator>
     650      inline bool
     651      operator<(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
     652  	      const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
     653      { return __lhs._M_base() < __rhs._M_base(); }
     654  
     655    template<typename _Key, typename _Tp,
     656  	   typename _Compare, typename _Allocator>
     657      inline bool
     658      operator<=(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
     659  	       const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
     660      { return __lhs._M_base() <= __rhs._M_base(); }
     661  
     662    template<typename _Key, typename _Tp,
     663  	   typename _Compare, typename _Allocator>
     664      inline bool
     665      operator>=(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
     666  	       const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
     667      { return __lhs._M_base() >= __rhs._M_base(); }
     668  
     669    template<typename _Key, typename _Tp,
     670  	   typename _Compare, typename _Allocator>
     671      inline bool
     672      operator>(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
     673  	      const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
     674      { return __lhs._M_base() > __rhs._M_base(); }
     675  #endif // three-way comparison
     676  
     677    template<typename _Key, typename _Tp,
     678  	   typename _Compare, typename _Allocator>
     679      inline void
     680      swap(multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
     681  	 multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
     682      _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs)))
     683      { __lhs.swap(__rhs); }
     684  
     685  } // namespace __debug
     686  } // namespace std
     687  
     688  #endif