xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/debug/multimap.h (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 // Debugging multimap implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2022 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 
_GLIBCXX_VISIBILITY(default)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
689