libstdc++: map.h Source File

libstdc++

map.h
Go to the documentation of this file.
1// Debugging map implementation -*- C++ -*-
2
3// Copyright (C) 2003-2026 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/map.h
26 * This file is a GNU debug extension to the Standard C++ Library.
27 */
28
29#ifndef _GLIBCXX_DEBUG_MAP_H
30#define _GLIBCXX_DEBUG_MAP_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
37namespace std _GLIBCXX_VISIBILITY(default)
38{
39namespace __debug
40{
41 /// Class std::map 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 map
45 : public __gnu_debug::_Safe_container<
46 map<_Key, _Tp, _Compare, _Allocator>, _Allocator,
47 __gnu_debug::_Safe_node_sequence>,
48 public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator>
49 {
50 typedef _GLIBCXX_STD_C::map<
51 _Key, _Tp, _Compare, _Allocator> _Base;
52 typedef __gnu_debug::_Safe_container<
53 map, _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 map(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, map>
83 iterator;
84 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, map>
85 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 map() : _Base() { }
98
99 map(const map& __x)
100 : _Base(__x) { }
101
102 ~map() { }
103#else
104 map() = default;
105 map(const map&) = default;
106 map(map&&) = default;
107
108 map(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 map(const allocator_type& __a)
115 : _Base(__a) { }
116
117 map(const map& __m, const __type_identity_t<allocator_type>& __a)
118 : _Base(__m, __a) { }
119
120 map(map&& __m, const __type_identity_t<allocator_type>& __a)
121 noexcept( noexcept(_Base(std::move(__m), __a)) )
122 : _Safe(std::move(__m), __a),
123 _Base(std::move(__m), __a) { }
124
125 map(initializer_list<value_type> __l, const allocator_type& __a)
126 : _Base(__l, __a) { }
127
128 template<typename _InputIterator>
129 map(_InputIterator __first, _InputIterator __last,
130 const allocator_type& __a)
131 : _Base(__gnu_debug::__base(
132 __glibcxx_check_valid_constructor_range(__first, __last)),
133 __gnu_debug::__base(__last), __a)
134 { }
135
136#if __glibcxx_containers_ranges // C++ >= 23
137 /**
138 * @brief Construct a map from a range.
139 * @since C++23
140 */
141 template<std::__detail::__container_compatible_range<value_type> _Rg>
142 map(std::from_range_t __t, _Rg&& __rg,
143 const _Compare& __c,
144 const allocator_type& __a = allocator_type())
145 : _Base(__t, std::forward<_Rg>(__rg), __c, __a)
146 { }
147
148 template<std::__detail::__container_compatible_range<value_type> _Rg>
149 map(std::from_range_t __t, _Rg&& __rg,
150 const allocator_type& __a = allocator_type())
151 : _Base(__t, std::forward<_Rg>(__rg), __a)
152 { }
153#endif
154
155 ~map() = default;
156#endif
157
158 map(_Base_ref __x)
159 : _Base(__x._M_ref) { }
160
161 explicit map(const _Compare& __comp,
162 const _Allocator& __a = _Allocator())
163 : _Base(__comp, __a) { }
164
165 template<typename _InputIterator>
166 map(_InputIterator __first, _InputIterator __last,
167 const _Compare& __comp = _Compare(),
168 const _Allocator& __a = _Allocator())
169 : _Base(__gnu_debug::__base(
170 __glibcxx_check_valid_constructor_range(__first, __last)),
171 __gnu_debug::__base(__last),
172 __comp, __a) { }
173
174#if __cplusplus >= 201103L
175 map&
176 operator=(const map&) = default;
177
178 map&
179 operator=(map&&) = default;
180
181 map&
182 operator=(initializer_list<value_type> __l)
183 {
184 _Base::operator=(__l);
185 this->_M_invalidate_all();
186 return *this;
187 }
188#endif
189
190 // _GLIBCXX_RESOLVE_LIB_DEFECTS
191 // 133. map missing get_allocator()
192 using _Base::get_allocator;
193
194 // iterators:
195 iterator
196 begin() _GLIBCXX_NOEXCEPT
197 { return iterator(_Base::begin(), this); }
198
199 const_iterator
200 begin() const _GLIBCXX_NOEXCEPT
201 { return const_iterator(_Base::begin(), this); }
202
203 iterator
204 end() _GLIBCXX_NOEXCEPT
205 { return iterator(_Base::end(), this); }
206
207 const_iterator
208 end() const _GLIBCXX_NOEXCEPT
209 { return const_iterator(_Base::end(), this); }
210
211 reverse_iterator
212 rbegin() _GLIBCXX_NOEXCEPT
213 { return reverse_iterator(end()); }
214
215 const_reverse_iterator
216 rbegin() const _GLIBCXX_NOEXCEPT
217 { return const_reverse_iterator(end()); }
218
219 reverse_iterator
220 rend() _GLIBCXX_NOEXCEPT
221 { return reverse_iterator(begin()); }
222
223 const_reverse_iterator
224 rend() const _GLIBCXX_NOEXCEPT
225 { return const_reverse_iterator(begin()); }
226
227#if __cplusplus >= 201103L
228 const_iterator
229 cbegin() const noexcept
230 { return const_iterator(_Base::begin(), this); }
231
232 const_iterator
233 cend() const noexcept
234 { return const_iterator(_Base::end(), this); }
235
236 const_reverse_iterator
237 crbegin() const noexcept
238 { return const_reverse_iterator(end()); }
239
240 const_reverse_iterator
241 crend() const noexcept
242 { return const_reverse_iterator(begin()); }
243#endif
244
245 // capacity:
246 using _Base::empty;
247 using _Base::size;
248 using _Base::max_size;
249
250 // 23.3.1.2 element access:
251 using _Base::operator[];
252
253 // _GLIBCXX_RESOLVE_LIB_DEFECTS
254 // DR 464. Suggestion for new member functions in standard containers.
255 using _Base::at;
256
257 // modifiers:
258#if __cplusplus >= 201103L
259 template<typename... _Args>
260 std::pair<iterator, bool>
261 emplace(_Args&&... __args)
262 {
263 auto __res = _Base::emplace(std::forward<_Args>(__args)...);
264 return { { __res.first, this }, __res.second };
265 }
266
267 template<typename... _Args>
268 iterator
269 emplace_hint(const_iterator __pos, _Args&&... __args)
270 {
271 __glibcxx_check_insert(__pos);
272 return
273 {
274 _Base::emplace_hint(__pos.base(), std::forward<_Args>(__args)...),
275 this
276 };
277 }
278#endif
279
280 std::pair<iterator, bool>
281 insert(const value_type& __x)
282 {
283 std::pair<_Base_iterator, bool> __res = _Base::insert(__x);
284 return std::pair<iterator, bool>(iterator(__res.first, this),
285 __res.second);
286 }
287
288#if __cplusplus >= 201103L
289 // _GLIBCXX_RESOLVE_LIB_DEFECTS
290 // 2354. Unnecessary copying when inserting into maps with braced-init
291 std::pair<iterator, bool>
292 insert(value_type&& __x)
293 {
294 auto __res = _Base::insert(std::move(__x));
295 return { { __res.first, this }, __res.second };
296 }
297
298 template<typename _Pair, typename = typename
299 std::enable_if<std::is_constructible<value_type,
300 _Pair&&>::value>::type>
301 std::pair<iterator, bool>
302 insert(_Pair&& __x)
303 {
304 auto __res = _Base::insert(std::forward<_Pair>(__x));
305 return { { __res.first, this }, __res.second };
306 }
307#endif
308
309#if __cplusplus >= 201103L
310 void
311 insert(std::initializer_list<value_type> __list)
312 { _Base::insert(__list); }
313#endif
314
315 iterator
316#if __cplusplus >= 201103L
317 insert(const_iterator __position, const value_type& __x)
318#else
319 insert(iterator __position, const value_type& __x)
320#endif
321 {
322 __glibcxx_check_insert(__position);
323 return iterator(_Base::insert(__position.base(), __x), this);
324 }
325
326#if __cplusplus >= 201103L
327 // _GLIBCXX_RESOLVE_LIB_DEFECTS
328 // 2354. Unnecessary copying when inserting into maps with braced-init
329 iterator
330 insert(const_iterator __position, value_type&& __x)
331 {
332 __glibcxx_check_insert(__position);
333 return { _Base::insert(__position.base(), std::move(__x)), this };
334 }
335
336 template<typename _Pair, typename = typename
337 std::enable_if<std::is_constructible<value_type,
338 _Pair&&>::value>::type>
339 iterator
340 insert(const_iterator __position, _Pair&& __x)
341 {
342 __glibcxx_check_insert(__position);
343 return
344 {
345 _Base::insert(__position.base(), std::forward<_Pair>(__x)),
346 this
347 };
348 }
349#endif
350
351 template<typename _InputIterator>
352 void
353 insert(_InputIterator __first, _InputIterator __last)
354 {
355 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
356 __glibcxx_check_valid_range2(__first, __last, __dist);
357
358 if (__dist.second >= __gnu_debug::__dp_sign)
359 _Base::insert(__gnu_debug::__unsafe(__first),
360 __gnu_debug::__unsafe(__last));
361 else
362 _Base::insert(__first, __last);
363 }
364
365
366#ifdef __glibcxx_map_try_emplace // C++ >= 17 && HOSTED
367 template <typename... _Args>
368 pair<iterator, bool>
369 try_emplace(const key_type& __k, _Args&&... __args)
370 {
371 auto __res = _Base::try_emplace(__k,
372 std::forward<_Args>(__args)...);
373 return { { __res.first, this }, __res.second };
374 }
375
376 template <typename... _Args>
377 pair<iterator, bool>
378 try_emplace(key_type&& __k, _Args&&... __args)
379 {
380 auto __res = _Base::try_emplace(std::move(__k),
381 std::forward<_Args>(__args)...);
382 return { { __res.first, this }, __res.second };
383 }
384
385# ifdef __glibcxx_associative_heterogeneous_insertion
386 template <__heterogeneous_tree_key<map> _Kt, typename... _Args>
387 pair<iterator, bool>
388 try_emplace(_Kt&& __k, _Args&&... __args)
389 {
390 auto __res = _Base::try_emplace(
391 std::forward<_Kt>(__k), std::forward<_Args>(__args)...);
392 return { { __res.first, this }, __res.second };
393 }
394#endif
395
396 template <typename... _Args>
397 iterator
398 try_emplace(const_iterator __hint, const key_type& __k,
399 _Args&&... __args)
400 {
401 __glibcxx_check_insert(__hint);
402 auto __it = _Base::try_emplace(__hint.base(), __k,
403 std::forward<_Args>(__args)...);
404 return { __it, this };
405 }
406
407 template <typename... _Args>
408 iterator
409 try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args)
410 {
411 __glibcxx_check_insert(__hint);
412 auto __it = _Base::try_emplace(__hint.base(), std::move(__k),
413 std::forward<_Args>(__args)...);
414 return { __it, this };
415 }
416
417# ifdef __glibcxx_associative_heterogeneous_insertion
418 template <__heterogeneous_tree_key<map> _Kt, typename... _Args>
419 iterator
420 try_emplace(const_iterator __hint, _Kt&& __k, _Args&&... __args)
421 {
422 __glibcxx_check_insert(__hint);
423 auto __it = _Base::try_emplace(__hint.base(),
424 std::forward<_Kt>(__k), std::forward<_Args>(__args)...);
425 return { __it, this };
426 }
427# endif
428
429 template <typename _Obj>
430 std::pair<iterator, bool>
431 insert_or_assign(const key_type& __k, _Obj&& __obj)
432 {
433 auto __res = _Base::insert_or_assign(__k,
434 std::forward<_Obj>(__obj));
435 return { { __res.first, this }, __res.second };
436 }
437
438 template <typename _Obj>
439 std::pair<iterator, bool>
440 insert_or_assign(key_type&& __k, _Obj&& __obj)
441 {
442 auto __res = _Base::insert_or_assign(std::move(__k),
443 std::forward<_Obj>(__obj));
444 return { { __res.first, this }, __res.second };
445 }
446
447# ifdef __glibcxx_associative_heterogeneous_insertion
448 template <__heterogeneous_tree_key<map> _Kt, typename _Obj>
449 std::pair<iterator, bool>
450 insert_or_assign(_Kt&& __k, _Obj&& __obj)
451 {
452 auto __res = _Base::insert_or_assign(
453 std::forward<_Kt>(__k), std::forward<_Obj>(__obj));
454 return { { __res.first, this }, __res.second };
455 }
456#endif
457
458 template <typename _Obj>
459 iterator
460 insert_or_assign(const_iterator __hint,
461 const key_type& __k, _Obj&& __obj)
462 {
463 __glibcxx_check_insert(__hint);
464 auto __it = _Base::insert_or_assign(__hint.base(), __k,
465 std::forward<_Obj>(__obj));
466 return { __it, this };
467 }
468
469 template <typename _Obj>
470 iterator
471 insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj)
472 {
473 __glibcxx_check_insert(__hint);
474 auto __it = _Base::insert_or_assign(__hint.base(), std::move(__k),
475 std::forward<_Obj>(__obj));
476 return { __it, this };
477 }
478
479# ifdef __glibcxx_associative_heterogeneous_insertion
480 template <__heterogeneous_tree_key<map> _Kt, typename _Obj>
481 iterator
482 insert_or_assign(const_iterator __hint, _Kt&& __k, _Obj&& __obj)
483 {
484 __glibcxx_check_insert(__hint);
485 auto __it = _Base::insert_or_assign(__hint.base(),
486 std::forward<_Kt>(__k), std::forward<_Obj>(__obj));
487 return { __it, this };
488 }
489# endif
490
491#endif // C++17
492
493#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
494 using node_type = typename _Base::node_type;
495 using insert_return_type = _Node_insert_return<iterator, node_type>;
496
497 node_type
498 extract(const_iterator __position)
499 {
500 __glibcxx_check_erase(__position);
501 this->_M_invalidate_if(_Equal(__position.base()));
502 return _Base::extract(__position.base());
503 }
504
505 node_type
506 extract(const key_type& __key)
507 {
508 const auto __position = find(__key);
509 if (__position != end())
510 return extract(__position);
511 return {};
512 }
513
514# ifdef __glibcxx_associative_heterogeneous_erasure
515 template <__heterogeneous_tree_key<map> _Kt>
516 node_type
517 extract(_Kt&& __key)
518 {
519 const auto __position = find(__key);
520 if (__position != end())
521 return extract(__position);
522 return {};
523 }
524# endif
525
526 insert_return_type
527 insert(node_type&& __nh)
528 {
529 auto __ret = _Base::insert(std::move(__nh));
530 return
531 { { __ret.position, this }, __ret.inserted, std::move(__ret.node) };
532 }
533
534 iterator
535 insert(const_iterator __hint, node_type&& __nh)
536 {
537 __glibcxx_check_insert(__hint);
538 return { _Base::insert(__hint.base(), std::move(__nh)), this };
539 }
540
541 using _Base::merge;
542#endif // C++17
543
544#if __cplusplus >= 201103L
545 iterator
546 erase(const_iterator __position)
547 {
548 __glibcxx_check_erase(__position);
549 return { erase(__position.base()), this };
550 }
551
552 _Base_iterator
553 erase(_Base_const_iterator __position)
554 {
555 __glibcxx_check_erase2(__position);
556 this->_M_invalidate_if(_Equal(__position));
557 return _Base::erase(__position);
558 }
559
560 _GLIBCXX_ABI_TAG_CXX11
561 iterator
562 erase(iterator __position)
563 { return erase(const_iterator(__position)); }
564#else
565 void
566 erase(iterator __position)
567 {
568 __glibcxx_check_erase(__position);
569 this->_M_invalidate_if(_Equal(__position.base()));
570 _Base::erase(__position.base());
571 }
572#endif
573
574 size_type
575 erase(const key_type& __x)
576 {
577 _Base_iterator __victim = _Base::find(__x);
578 if (__victim == _Base::end())
579 return 0;
580 else
581 {
582 this->_M_invalidate_if(_Equal(__victim));
583 _Base::erase(__victim);
584 return 1;
585 }
586 }
587
588# ifdef __glibcxx_associative_heterogeneous_erasure
589 // Note that for some types _Kt this may erase more than
590 // one element, such as if _Kt::operator< checks only part
591 // of the key.
592 template <__heterogeneous_tree_key<map> _Kt>
593 size_type
594 erase(_Kt&& __x)
595 {
596 auto __victims = _Base::equal_range(__x);
597 size_type __count = 0;
598 for (auto __victim = __victims.first; __victim != __victims.second;)
599 {
600 this->_M_invalidate_if(_Equal(__victim));
601 _Base::erase(__victim++);
602 ++__count;
603 }
604 return __count;
605 }
606# endif
607
608#if __cplusplus >= 201103L
609 iterator
610 erase(const_iterator __first, const_iterator __last)
611 {
612 // _GLIBCXX_RESOLVE_LIB_DEFECTS
613 // 151. can't currently clear() empty container
614 __glibcxx_check_erase_range(__first, __last);
615 for (_Base_const_iterator __victim = __first.base();
616 __victim != __last.base(); ++__victim)
617 {
618 _GLIBCXX_DEBUG_VERIFY(__victim != _Base::cend(),
619 _M_message(__gnu_debug::__msg_valid_range)
620 ._M_iterator(__first, "first")
621 ._M_iterator(__last, "last"));
622 this->_M_invalidate_if(_Equal(__victim));
623 }
624
625 return { _Base::erase(__first.base(), __last.base()), this };
626 }
627#else
628 void
629 erase(iterator __first, iterator __last)
630 {
631 // _GLIBCXX_RESOLVE_LIB_DEFECTS
632 // 151. can't currently clear() empty container
633 __glibcxx_check_erase_range(__first, __last);
634 for (_Base_iterator __victim = __first.base();
635 __victim != __last.base(); ++__victim)
636 {
637 _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
638 _M_message(__gnu_debug::__msg_valid_range)
639 ._M_iterator(__first, "first")
640 ._M_iterator(__last, "last"));
641 this->_M_invalidate_if(_Equal(__victim));
642 }
643 _Base::erase(__first.base(), __last.base());
644 }
645#endif
646
647 void
648 swap(map& __x)
649 _GLIBCXX_NOEXCEPT_IF( noexcept(declval<_Base&>().swap(__x)) )
650 {
651 _Safe::_M_swap(__x);
652 _Base::swap(__x);
653 }
654
655 void
656 clear() _GLIBCXX_NOEXCEPT
657 {
658 this->_M_invalidate_all();
659 _Base::clear();
660 }
661
662 // observers:
663 using _Base::key_comp;
664 using _Base::value_comp;
665
666 // 23.3.1.3 map operations:
667 iterator
668 find(const key_type& __x)
669 { return iterator(_Base::find(__x), this); }
670
671#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
672 template<typename _Kt,
673 typename _Req =
674 typename __has_is_transparent<_Compare, _Kt>::type>
675 iterator
676 find(const _Kt& __x)
677 { return { _Base::find(__x), this }; }
678#endif
679
680 const_iterator
681 find(const key_type& __x) const
682 { return const_iterator(_Base::find(__x), this); }
683
684#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
685 template<typename _Kt,
686 typename _Req =
687 typename __has_is_transparent<_Compare, _Kt>::type>
688 const_iterator
689 find(const _Kt& __x) const
690 { return { _Base::find(__x), this }; }
691#endif
692
693 using _Base::count;
694
695 iterator
696 lower_bound(const key_type& __x)
697 { return iterator(_Base::lower_bound(__x), this); }
698
699#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
700 template<typename _Kt,
701 typename _Req =
702 typename __has_is_transparent<_Compare, _Kt>::type>
703 iterator
704 lower_bound(const _Kt& __x)
705 { return { _Base::lower_bound(__x), this }; }
706#endif
707
708 const_iterator
709 lower_bound(const key_type& __x) const
710 { return const_iterator(_Base::lower_bound(__x), this); }
711
712#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
713 template<typename _Kt,
714 typename _Req =
715 typename __has_is_transparent<_Compare, _Kt>::type>
716 const_iterator
717 lower_bound(const _Kt& __x) const
718 { return { _Base::lower_bound(__x), this }; }
719#endif
720
721 iterator
722 upper_bound(const key_type& __x)
723 { return iterator(_Base::upper_bound(__x), this); }
724
725#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
726 template<typename _Kt,
727 typename _Req =
728 typename __has_is_transparent<_Compare, _Kt>::type>
729 iterator
730 upper_bound(const _Kt& __x)
731 { return { _Base::upper_bound(__x), this }; }
732#endif
733
734 const_iterator
735 upper_bound(const key_type& __x) const
736 { return const_iterator(_Base::upper_bound(__x), this); }
737
738#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
739 template<typename _Kt,
740 typename _Req =
741 typename __has_is_transparent<_Compare, _Kt>::type>
742 const_iterator
743 upper_bound(const _Kt& __x) const
744 { return { _Base::upper_bound(__x), this }; }
745#endif
746
747 std::pair<iterator,iterator>
748 equal_range(const key_type& __x)
749 {
750 std::pair<_Base_iterator, _Base_iterator> __res =
751 _Base::equal_range(__x);
752 return std::make_pair(iterator(__res.first, this),
753 iterator(__res.second, this));
754 }
755
756#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
757 template<typename _Kt,
758 typename _Req =
759 typename __has_is_transparent<_Compare, _Kt>::type>
760 std::pair<iterator, iterator>
761 equal_range(const _Kt& __x)
762 {
763 auto __res = _Base::equal_range(__x);
764 return { { __res.first, this }, { __res.second, this } };
765 }
766#endif
767
768 std::pair<const_iterator,const_iterator>
769 equal_range(const key_type& __x) const
770 {
771 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
772 _Base::equal_range(__x);
773 return std::make_pair(const_iterator(__res.first, this),
774 const_iterator(__res.second, this));
775 }
776
777#ifdef __glibcxx_generic_associative_lookup // C++ >= 14
778 template<typename _Kt,
779 typename _Req =
780 typename __has_is_transparent<_Compare, _Kt>::type>
781 std::pair<const_iterator, const_iterator>
782 equal_range(const _Kt& __x) const
783 {
784 auto __res = _Base::equal_range(__x);
785 return { { __res.first, this }, { __res.second, this } };
786 }
787#endif
788
789 _Base&
790 _M_base() _GLIBCXX_NOEXCEPT { return *this; }
791
792 const _Base&
793 _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
794 };
795
796#if __cpp_deduction_guides >= 201606
797
798 template<typename _InputIterator,
799 typename _Compare = less<__iter_key_t<_InputIterator>>,
800 typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>,
801 typename = _RequireInputIter<_InputIterator>,
802 typename = _RequireNotAllocator<_Compare>,
803 typename = _RequireAllocator<_Allocator>>
804 map(_InputIterator, _InputIterator,
805 _Compare = _Compare(), _Allocator = _Allocator())
806 -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>,
807 _Compare, _Allocator>;
808
809 template<typename _Key, typename _Tp, typename _Compare = less<_Key>,
810 typename _Allocator = allocator<pair<const _Key, _Tp>>,
811 typename = _RequireNotAllocator<_Compare>,
812 typename = _RequireAllocator<_Allocator>>
813 map(initializer_list<pair<_Key, _Tp>>,
814 _Compare = _Compare(), _Allocator = _Allocator())
815 -> map<_Key, _Tp, _Compare, _Allocator>;
816
817 template <typename _InputIterator, typename _Allocator,
818 typename = _RequireInputIter<_InputIterator>,
819 typename = _RequireAllocator<_Allocator>>
820 map(_InputIterator, _InputIterator, _Allocator)
821 -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>,
822 less<__iter_key_t<_InputIterator>>, _Allocator>;
823
824 template<typename _Key, typename _Tp, typename _Allocator,
825 typename = _RequireAllocator<_Allocator>>
826 map(initializer_list<pair<_Key, _Tp>>, _Allocator)
827 -> map<_Key, _Tp, less<_Key>, _Allocator>;
828
829#if __glibcxx_containers_ranges // C++ >= 23
830 template<ranges::input_range _Rg,
831 __not_allocator_like _Compare = less<__detail::__range_key_type<_Rg>>,
832 __allocator_like _Alloc =
833 std::allocator<__detail::__range_to_alloc_type<_Rg>>>
834 map(from_range_t, _Rg&&, _Compare = _Compare(), _Alloc = _Alloc())
835 -> map<__detail::__range_key_type<_Rg>,
836 __detail::__range_mapped_type<_Rg>,
837 _Compare, _Alloc>;
838
839 template<ranges::input_range _Rg, __allocator_like _Alloc>
840 map(from_range_t, _Rg&&, _Alloc)
841 -> map<__detail::__range_key_type<_Rg>,
842 __detail::__range_mapped_type<_Rg>,
843 less<__detail::__range_key_type<_Rg>>,
844 _Alloc>;
845#endif
846#endif // deduction guides
847
848 template<typename _Key, typename _Tp,
849 typename _Compare, typename _Allocator>
850 inline bool
851 operator==(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
852 const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
853 { return __lhs._M_base() == __rhs._M_base(); }
854
855#if __cpp_lib_three_way_comparison
856 template<typename _Key, typename _Tp, typename _Compare, typename _Alloc>
857 inline __detail::__synth3way_t<pair<const _Key, _Tp>>
858 operator<=>(const map<_Key, _Tp, _Compare, _Alloc>& __lhs,
859 const map<_Key, _Tp, _Compare, _Alloc>& __rhs)
860 { return __lhs._M_base() <=> __rhs._M_base(); }
861#else
862 template<typename _Key, typename _Tp,
863 typename _Compare, typename _Allocator>
864 inline bool
865 operator!=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
866 const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
867 { return __lhs._M_base() != __rhs._M_base(); }
868
869 template<typename _Key, typename _Tp,
870 typename _Compare, typename _Allocator>
871 inline bool
872 operator<(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
873 const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
874 { return __lhs._M_base() < __rhs._M_base(); }
875
876 template<typename _Key, typename _Tp,
877 typename _Compare, typename _Allocator>
878 inline bool
879 operator<=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
880 const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
881 { return __lhs._M_base() <= __rhs._M_base(); }
882
883 template<typename _Key, typename _Tp,
884 typename _Compare, typename _Allocator>
885 inline bool
886 operator>=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
887 const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
888 { return __lhs._M_base() >= __rhs._M_base(); }
889
890 template<typename _Key, typename _Tp,
891 typename _Compare, typename _Allocator>
892 inline bool
893 operator>(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
894 const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
895 { return __lhs._M_base() > __rhs._M_base(); }
896#endif // three-way comparison
897
898 template<typename _Key, typename _Tp,
899 typename _Compare, typename _Allocator>
900 inline void
901 swap(map<_Key, _Tp, _Compare, _Allocator>& __lhs,
902 map<_Key, _Tp, _Compare, _Allocator>& __rhs)
903 _GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs)))
904 { __lhs.swap(__rhs); }
905
906} // namespace __debug
907} // namespace std
908
909#endif
stl_pair.h
__glibcxx_check_insert
#define __glibcxx_check_insert(_Position)
Definition macros.h:143
__glibcxx_check_erase_range
#define __glibcxx_check_erase_range(_First, _Last)
Definition macros.h:245
__glibcxx_check_erase
#define __glibcxx_check_erase(_Position)
Definition macros.h:209
safe_container.h
safe_iterator.h
safe_sequence.h
std::chrono::operator<=
constexpr bool operator<=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:863
std::chrono::operator>=
constexpr bool operator>=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:877
std::chrono::operator<
constexpr bool operator<(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:830
std::chrono::operator>
constexpr bool operator>(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:870
std::pair::pair
pair(_T1, _T2) -> pair< _T1, _T2 >
Two pairs are equal iff their members are equal.
std::make_pair
constexpr pair< typename __decay_and_strip< _T1 >::__type, typename __decay_and_strip< _T2 >::__type > make_pair(_T1 &&__x, _T2 &&__y)
A convenience wrapper for creating a pair from two objects.
Definition stl_pair.h:1169
std::declval
auto declval() noexcept -> decltype(__declval< _Tp >(0))
Definition type_traits:2741
std::move
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:138
std::forward
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:72
std
ISO C++ entities toplevel namespace is std.
__gnu_debug::__base
constexpr _Iterator __base(_Iterator __it)
Definition helper_functions.h:339
std::__debug
GNU debug code, replaces standard behavior with debug behavior.
std::initializer_list
initializer_list
Definition initializer_list:48
std::enable_if
Define a member typedef type only if a boolean constant is true.
Definition type_traits:137
std::is_constructible
is_constructible
Definition type_traits:1265
std::allocator
The standard allocator, as per C++03 [20.4.1].
Definition allocator.h:134
__gnu_debug::_Safe_iterator
Safe iterator wrapper.
Definition safe_iterator.h:133
__gnu_debug::_Safe_iterator::base
constexpr _Iterator & base() noexcept
Return the underlying iterator.
Definition safe_iterator.h:433
std::less
One of the comparison functors.
Definition stl_function.h:404
std::reverse_iterator
Definition bits/stl_iterator.h:137
std::pair
Struct holding two objects (or references) of arbitrary type.
Definition stl_pair.h:307
std::pair::first
_T1 first
The first member.
Definition stl_pair.h:311
std::pair::second
_T2 second
The second member.
Definition stl_pair.h:312
std::map
A standard container made up of (key,value) pairs, which can be retrieved based on a key,...
Definition stl_map.h:107
std::__debug::map
Class std::map with safety/checking/debug instrumentation.
Definition map.h:49
__gnu_debug::_Safe_container
Safe class dealing with some allocator dependent operations.
Definition safe_container.h:43
__gnu_debug::_Equal_to
Definition safe_sequence.h:61
__gnu_debug::_Safe_node_sequence
Like _Safe_sequence but with a special _M_invalidate_all implementation not invalidating past-the-end...
Definition safe_sequence.h:147
std::ranges::input_range
A range for which ranges::begin returns an input iterator.
Definition ranges_base.h:599