libstdc++
debug/unordered_map
Go to the documentation of this file.
1 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2020 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/unordered_map
26  * This file is a GNU debug extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_DEBUG_UNORDERED_MAP
30 #define _GLIBCXX_DEBUG_UNORDERED_MAP 1
31 
32 #pragma GCC system_header
33 
34 #if __cplusplus < 201103L
35 # include <bits/c++0x_warning.h>
36 #else
37 # include <bits/c++config.h>
38 namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug {
39  template<typename _Key, typename _Tp, typename _Hash, typename _Pred,
40  typename _Allocator>
42  template<typename _Key, typename _Tp, typename _Hash, typename _Pred,
43  typename _Allocator>
45 } } // namespace std::__debug
46 
47 # include <unordered_map>
48 
50 #include <debug/safe_container.h>
51 #include <debug/safe_iterator.h>
53 
54 namespace std _GLIBCXX_VISIBILITY(default)
55 {
56 namespace __debug
57 {
58  /// Class std::unordered_map with safety/checking/debug instrumentation.
59  template<typename _Key, typename _Tp,
60  typename _Hash = std::hash<_Key>,
61  typename _Pred = std::equal_to<_Key>,
62  typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
63  class unordered_map
65  unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
66  __gnu_debug::_Safe_unordered_container>,
67  public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
68  {
69  typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
70  _Pred, _Alloc> _Base;
73  typedef typename _Base::const_iterator _Base_const_iterator;
74  typedef typename _Base::iterator _Base_iterator;
75  typedef typename _Base::const_local_iterator
76  _Base_const_local_iterator;
77  typedef typename _Base::local_iterator _Base_local_iterator;
78 
79  template<typename _ItT, typename _SeqT, typename _CatT>
80  friend class ::__gnu_debug::_Safe_iterator;
81  template<typename _ItT, typename _SeqT>
82  friend class ::__gnu_debug::_Safe_local_iterator;
83 
84  public:
85  typedef typename _Base::size_type size_type;
86  typedef typename _Base::hasher hasher;
87  typedef typename _Base::key_equal key_equal;
88  typedef typename _Base::allocator_type allocator_type;
89 
90  typedef typename _Base::key_type key_type;
91  typedef typename _Base::value_type value_type;
92 
94  _Base_iterator, unordered_map> iterator;
96  _Base_const_iterator, unordered_map> const_iterator;
98  _Base_local_iterator, unordered_map> local_iterator;
100  _Base_const_local_iterator, unordered_map> const_local_iterator;
101 
102  unordered_map() = default;
103 
104  explicit
105  unordered_map(size_type __n,
106  const hasher& __hf = hasher(),
107  const key_equal& __eql = key_equal(),
108  const allocator_type& __a = allocator_type())
109  : _Base(__n, __hf, __eql, __a) { }
110 
111  template<typename _InputIterator>
112  unordered_map(_InputIterator __first, _InputIterator __last,
113  size_type __n = 0,
114  const hasher& __hf = hasher(),
115  const key_equal& __eql = key_equal(),
116  const allocator_type& __a = allocator_type())
117  : _Base(__gnu_debug::__base(
118  __glibcxx_check_valid_constructor_range(__first, __last)),
119  __gnu_debug::__base(__last), __n,
120  __hf, __eql, __a) { }
121 
122  unordered_map(const unordered_map&) = default;
123 
124  unordered_map(const _Base& __x)
125  : _Base(__x) { }
126 
127  unordered_map(unordered_map&&) = default;
128 
129  explicit
130  unordered_map(const allocator_type& __a)
131  : _Base(__a) { }
132 
133  unordered_map(const unordered_map& __umap,
134  const allocator_type& __a)
135  : _Base(__umap, __a) { }
136 
137  unordered_map(unordered_map&& __umap,
138  const allocator_type& __a)
139  : _Safe(std::move(__umap._M_safe()), __a),
140  _Base(std::move(__umap._M_base()), __a) { }
141 
142  unordered_map(initializer_list<value_type> __l,
143  size_type __n = 0,
144  const hasher& __hf = hasher(),
145  const key_equal& __eql = key_equal(),
146  const allocator_type& __a = allocator_type())
147  : _Base(__l, __n, __hf, __eql, __a) { }
148 
149  unordered_map(size_type __n, const allocator_type& __a)
150  : unordered_map(__n, hasher(), key_equal(), __a)
151  { }
152 
153  unordered_map(size_type __n,
154  const hasher& __hf,
155  const allocator_type& __a)
156  : unordered_map(__n, __hf, key_equal(), __a)
157  { }
158 
159  template<typename _InputIterator>
160  unordered_map(_InputIterator __first, _InputIterator __last,
161  size_type __n,
162  const allocator_type& __a)
163  : unordered_map(__first, __last, __n, hasher(), key_equal(), __a)
164  { }
165 
166  template<typename _InputIterator>
167  unordered_map(_InputIterator __first, _InputIterator __last,
168  size_type __n,
169  const hasher& __hf,
170  const allocator_type& __a)
171  : unordered_map(__first, __last, __n, __hf, key_equal(), __a)
172  { }
173 
174  unordered_map(initializer_list<value_type> __l,
175  size_type __n,
176  const allocator_type& __a)
177  : unordered_map(__l, __n, hasher(), key_equal(), __a)
178  { }
179 
180  unordered_map(initializer_list<value_type> __l,
181  size_type __n,
182  const hasher& __hf,
183  const allocator_type& __a)
184  : unordered_map(__l, __n, __hf, key_equal(), __a)
185  { }
186 
187  ~unordered_map() = default;
188 
189  unordered_map&
190  operator=(const unordered_map&) = default;
191 
192  unordered_map&
193  operator=(unordered_map&&) = default;
194 
195  unordered_map&
196  operator=(initializer_list<value_type> __l)
197  {
198  _M_base() = __l;
199  this->_M_invalidate_all();
200  return *this;
201  }
202 
203  void
204  swap(unordered_map& __x)
205  noexcept( noexcept(declval<_Base&>().swap(__x)) )
206  {
207  _Safe::_M_swap(__x);
208  _Base::swap(__x);
209  }
210 
211  void
212  clear() noexcept
213  {
214  _Base::clear();
215  this->_M_invalidate_all();
216  }
217 
218  iterator
219  begin() noexcept
220  { return { _Base::begin(), this }; }
221 
222  const_iterator
223  begin() const noexcept
224  { return { _Base::begin(), this }; }
225 
226  iterator
227  end() noexcept
228  { return { _Base::end(), this }; }
229 
230  const_iterator
231  end() const noexcept
232  { return { _Base::end(), this }; }
233 
234  const_iterator
235  cbegin() const noexcept
236  { return { _Base::cbegin(), this }; }
237 
238  const_iterator
239  cend() const noexcept
240  { return { _Base::cend(), this }; }
241 
242  // local versions
243  local_iterator
244  begin(size_type __b)
245  {
246  __glibcxx_check_bucket_index(__b);
247  return { _Base::begin(__b), this };
248  }
249 
250  local_iterator
251  end(size_type __b)
252  {
253  __glibcxx_check_bucket_index(__b);
254  return { _Base::end(__b), this };
255  }
256 
257  const_local_iterator
258  begin(size_type __b) const
259  {
260  __glibcxx_check_bucket_index(__b);
261  return { _Base::begin(__b), this };
262  }
263 
264  const_local_iterator
265  end(size_type __b) const
266  {
267  __glibcxx_check_bucket_index(__b);
268  return { _Base::end(__b), this };
269  }
270 
271  const_local_iterator
272  cbegin(size_type __b) const
273  {
274  __glibcxx_check_bucket_index(__b);
275  return { _Base::cbegin(__b), this };
276  }
277 
278  const_local_iterator
279  cend(size_type __b) const
280  {
281  __glibcxx_check_bucket_index(__b);
282  return { _Base::cend(__b), this };
283  }
284 
285  size_type
286  bucket_size(size_type __b) const
287  {
288  __glibcxx_check_bucket_index(__b);
289  return _Base::bucket_size(__b);
290  }
291 
292  float
293  max_load_factor() const noexcept
294  { return _Base::max_load_factor(); }
295 
296  void
297  max_load_factor(float __f)
298  {
299  __glibcxx_check_max_load_factor(__f);
300  _Base::max_load_factor(__f);
301  }
302 
303  template<typename... _Args>
305  emplace(_Args&&... __args)
306  {
307  size_type __bucket_count = this->bucket_count();
308  auto __res = _Base::emplace(std::forward<_Args>(__args)...);
309  _M_check_rehashed(__bucket_count);
310  return { { __res.first, this }, __res.second };
311  }
312 
313  template<typename... _Args>
314  iterator
315  emplace_hint(const_iterator __hint, _Args&&... __args)
316  {
317  __glibcxx_check_insert(__hint);
318  size_type __bucket_count = this->bucket_count();
319  auto __it = _Base::emplace_hint(__hint.base(),
320  std::forward<_Args>(__args)...);
321  _M_check_rehashed(__bucket_count);
322  return { __it, this };
323  }
324 
326  insert(const value_type& __obj)
327  {
328  size_type __bucket_count = this->bucket_count();
329  auto __res = _Base::insert(__obj);
330  _M_check_rehashed(__bucket_count);
331  return { { __res.first, this }, __res.second };
332  }
333 
334  // _GLIBCXX_RESOLVE_LIB_DEFECTS
335  // 2354. Unnecessary copying when inserting into maps with braced-init
337  insert(value_type&& __x)
338  {
339  size_type __bucket_count = this->bucket_count();
340  auto __res = _Base::insert(std::move(__x));
341  _M_check_rehashed(__bucket_count);
342  return { { __res.first, this }, __res.second };
343  }
344 
345  template<typename _Pair, typename = typename
347  _Pair&&>::value>::type>
349  insert(_Pair&& __obj)
350  {
351  size_type __bucket_count = this->bucket_count();
352  auto __res = _Base::insert(std::forward<_Pair>(__obj));
353  _M_check_rehashed(__bucket_count);
354  return { { __res.first, this }, __res.second };
355  }
356 
357  iterator
358  insert(const_iterator __hint, const value_type& __obj)
359  {
360  __glibcxx_check_insert(__hint);
361  size_type __bucket_count = this->bucket_count();
362  auto __it = _Base::insert(__hint.base(), __obj);
363  _M_check_rehashed(__bucket_count);
364  return { __it, this };
365  }
366 
367  // _GLIBCXX_RESOLVE_LIB_DEFECTS
368  // 2354. Unnecessary copying when inserting into maps with braced-init
369  iterator
370  insert(const_iterator __hint, value_type&& __x)
371  {
372  __glibcxx_check_insert(__hint);
373  size_type __bucket_count = this->bucket_count();
374  auto __it = _Base::insert(__hint.base(), std::move(__x));
375  _M_check_rehashed(__bucket_count);
376  return { __it, this };
377  }
378 
379  template<typename _Pair, typename = typename
381  _Pair&&>::value>::type>
382  iterator
383  insert(const_iterator __hint, _Pair&& __obj)
384  {
385  __glibcxx_check_insert(__hint);
386  size_type __bucket_count = this->bucket_count();
387  auto __it = _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
388  _M_check_rehashed(__bucket_count);
389  return { __it, this };
390  }
391 
392  void
394  {
395  size_type __bucket_count = this->bucket_count();
396  _Base::insert(__l);
397  _M_check_rehashed(__bucket_count);
398  }
399 
400  template<typename _InputIterator>
401  void
402  insert(_InputIterator __first, _InputIterator __last)
403  {
405  __glibcxx_check_valid_range2(__first, __last, __dist);
406  size_type __bucket_count = this->bucket_count();
407 
408  if (__dist.second >= __gnu_debug::__dp_sign)
409  _Base::insert(__gnu_debug::__unsafe(__first),
410  __gnu_debug::__unsafe(__last));
411  else
412  _Base::insert(__first, __last);
413 
414  _M_check_rehashed(__bucket_count);
415  }
416 
417 #if __cplusplus > 201402L
418  template <typename... _Args>
419  pair<iterator, bool>
420  try_emplace(const key_type& __k, _Args&&... __args)
421  {
422  auto __res = _Base::try_emplace(__k,
423  std::forward<_Args>(__args)...);
424  return { { __res.first, this }, __res.second };
425  }
426 
427  template <typename... _Args>
428  pair<iterator, bool>
429  try_emplace(key_type&& __k, _Args&&... __args)
430  {
431  auto __res = _Base::try_emplace(std::move(__k),
432  std::forward<_Args>(__args)...);
433  return { { __res.first, this }, __res.second };
434  }
435 
436  template <typename... _Args>
437  iterator
438  try_emplace(const_iterator __hint, const key_type& __k,
439  _Args&&... __args)
440  {
441  __glibcxx_check_insert(__hint);
442  return { _Base::try_emplace(__hint.base(), __k,
443  std::forward<_Args>(__args)...),
444  this };
445  }
446 
447  template <typename... _Args>
448  iterator
449  try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args)
450  {
451  __glibcxx_check_insert(__hint);
452  return { _Base::try_emplace(__hint.base(), std::move(__k),
453  std::forward<_Args>(__args)...),
454  this };
455  }
456 
457  template <typename _Obj>
458  pair<iterator, bool>
459  insert_or_assign(const key_type& __k, _Obj&& __obj)
460  {
461  auto __res = _Base::insert_or_assign(__k,
462  std::forward<_Obj>(__obj));
463  return { { __res.first, this }, __res.second };
464  }
465 
466  template <typename _Obj>
467  pair<iterator, bool>
468  insert_or_assign(key_type&& __k, _Obj&& __obj)
469  {
470  auto __res = _Base::insert_or_assign(std::move(__k),
471  std::forward<_Obj>(__obj));
472  return { { __res.first, this }, __res.second };
473  }
474 
475  template <typename _Obj>
476  iterator
477  insert_or_assign(const_iterator __hint, const key_type& __k,
478  _Obj&& __obj)
479  {
480  __glibcxx_check_insert(__hint);
481  return { _Base::insert_or_assign(__hint.base(), __k,
482  std::forward<_Obj>(__obj)),
483  this };
484  }
485 
486  template <typename _Obj>
487  iterator
488  insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj)
489  {
490  __glibcxx_check_insert(__hint);
491  return { _Base::insert_or_assign(__hint.base(), std::move(__k),
492  std::forward<_Obj>(__obj)),
493  this };
494  }
495 #endif // C++17
496 
497 #if __cplusplus > 201402L
498  using node_type = typename _Base::node_type;
499  using insert_return_type = _Node_insert_return<iterator, node_type>;
500 
501  node_type
502  extract(const_iterator __position)
503  {
504  __glibcxx_check_erase(__position);
505  return _M_extract(__position.base());
506  }
507 
508  node_type
509  extract(const key_type& __key)
510  {
511  const auto __position = _Base::find(__key);
512  if (__position != _Base::end())
513  return _M_extract(__position);
514  return {};
515  }
516 
517  insert_return_type
518  insert(node_type&& __nh)
519  {
520  auto __ret = _Base::insert(std::move(__nh));
521  return
522  { { __ret.position, this }, __ret.inserted, std::move(__ret.node) };
523  }
524 
525  iterator
526  insert(const_iterator __hint, node_type&& __nh)
527  {
528  __glibcxx_check_insert(__hint);
529  return { _Base::insert(__hint.base(), std::move(__nh)), this };
530  }
531 
532  using _Base::merge;
533 #endif // C++17
534 
535  iterator
536  find(const key_type& __key)
537  { return { _Base::find(__key), this }; }
538 
539  const_iterator
540  find(const key_type& __key) const
541  { return { _Base::find(__key), this }; }
542 
544  equal_range(const key_type& __key)
545  {
546  auto __res = _Base::equal_range(__key);
547  return { { __res.first, this }, { __res.second, this } };
548  }
549 
551  equal_range(const key_type& __key) const
552  {
553  auto __res = _Base::equal_range(__key);
554  return { { __res.first, this }, { __res.second, this } };
555  }
556 
557  size_type
558  erase(const key_type& __key)
559  {
560  size_type __ret(0);
561  auto __victim = _Base::find(__key);
562  if (__victim != _Base::end())
563  {
564  _M_erase(__victim);
565  __ret = 1;
566  }
567  return __ret;
568  }
569 
570  iterator
571  erase(const_iterator __it)
572  {
573  __glibcxx_check_erase(__it);
574  return { _M_erase(__it.base()), this };
575  }
576 
577  iterator
578  erase(iterator __it)
579  {
580  __glibcxx_check_erase(__it);
581  return { _M_erase(__it.base()), this };
582  }
583 
584  iterator
585  erase(const_iterator __first, const_iterator __last)
586  {
587  __glibcxx_check_erase_range(__first, __last);
588  for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp)
589  {
590  _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(),
591  _M_message(__gnu_debug::__msg_valid_range)
592  ._M_iterator(__first, "first")
593  ._M_iterator(__last, "last"));
594  _M_invalidate(__tmp);
595  }
596 
597  size_type __bucket_count = this->bucket_count();
598  auto __next = _Base::erase(__first.base(), __last.base());
599  _M_check_rehashed(__bucket_count);
600  return { __next, this };
601  }
602 
603  _Base&
604  _M_base() noexcept { return *this; }
605 
606  const _Base&
607  _M_base() const noexcept { return *this; }
608 
609  private:
610  void
611  _M_check_rehashed(size_type __prev_count)
612  {
613  if (__prev_count != this->bucket_count())
614  this->_M_invalidate_all();
615  }
616 
617  void
618  _M_invalidate(_Base_const_iterator __victim)
619  {
620  this->_M_invalidate_if(
621  [__victim](_Base_const_iterator __it) { return __it == __victim; });
623  [__victim](_Base_const_local_iterator __it)
624  { return __it._M_curr() == __victim._M_cur; });
625  }
626 
627  _Base_iterator
628  _M_erase(_Base_const_iterator __victim)
629  {
630  _M_invalidate(__victim);
631  size_type __bucket_count = this->bucket_count();
632  _Base_iterator __next = _Base::erase(__victim);
633  _M_check_rehashed(__bucket_count);
634  return __next;
635  }
636 
637 #if __cplusplus > 201402L
638  node_type
639  _M_extract(_Base_const_iterator __victim)
640  {
641  _M_invalidate(__victim);
642  return _Base::extract(__victim);
643  }
644 #endif
645  };
646 
647 #if __cpp_deduction_guides >= 201606
648 
649  template<typename _InputIterator,
650  typename _Hash = hash<__iter_key_t<_InputIterator>>,
651  typename _Pred = equal_to<__iter_key_t<_InputIterator>>,
652  typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>,
653  typename = _RequireInputIter<_InputIterator>,
654  typename = _RequireNotAllocatorOrIntegral<_Hash>,
655  typename = _RequireNotAllocator<_Pred>,
656  typename = _RequireAllocator<_Allocator>>
657  unordered_map(_InputIterator, _InputIterator,
658  typename unordered_map<int, int>::size_type = {},
659  _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
660  -> unordered_map<__iter_key_t<_InputIterator>,
661  __iter_val_t<_InputIterator>,
662  _Hash, _Pred, _Allocator>;
663 
664  template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
665  typename _Pred = equal_to<_Key>,
666  typename _Allocator = allocator<pair<const _Key, _Tp>>,
667  typename = _RequireNotAllocatorOrIntegral<_Hash>,
668  typename = _RequireNotAllocator<_Pred>,
669  typename = _RequireAllocator<_Allocator>>
670  unordered_map(initializer_list<pair<_Key, _Tp>>,
671  typename unordered_map<int, int>::size_type = {},
672  _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
673  -> unordered_map<_Key, _Tp, _Hash, _Pred, _Allocator>;
674 
675  template<typename _InputIterator, typename _Allocator,
676  typename = _RequireInputIter<_InputIterator>,
677  typename = _RequireAllocator<_Allocator>>
678  unordered_map(_InputIterator, _InputIterator,
679  typename unordered_map<int, int>::size_type, _Allocator)
680  -> unordered_map<__iter_key_t<_InputIterator>,
681  __iter_val_t<_InputIterator>,
682  hash<__iter_key_t<_InputIterator>>,
683  equal_to<__iter_key_t<_InputIterator>>,
684  _Allocator>;
685 
686  template<typename _InputIterator, typename _Allocator,
687  typename = _RequireInputIter<_InputIterator>,
688  typename = _RequireAllocator<_Allocator>>
689  unordered_map(_InputIterator, _InputIterator, _Allocator)
690  -> unordered_map<__iter_key_t<_InputIterator>,
691  __iter_val_t<_InputIterator>,
692  hash<__iter_key_t<_InputIterator>>,
693  equal_to<__iter_key_t<_InputIterator>>,
694  _Allocator>;
695 
696  template<typename _InputIterator, typename _Hash, typename _Allocator,
697  typename = _RequireInputIter<_InputIterator>,
698  typename = _RequireNotAllocatorOrIntegral<_Hash>,
699  typename = _RequireAllocator<_Allocator>>
700  unordered_map(_InputIterator, _InputIterator,
701  typename unordered_map<int, int>::size_type,
702  _Hash, _Allocator)
703  -> unordered_map<__iter_key_t<_InputIterator>,
704  __iter_val_t<_InputIterator>, _Hash,
705  equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
706 
707  template<typename _Key, typename _Tp, typename _Allocator,
708  typename = _RequireAllocator<_Allocator>>
709  unordered_map(initializer_list<pair<_Key, _Tp>>,
710  typename unordered_map<int, int>::size_type,
711  _Allocator)
712  -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>;
713 
714  template<typename _Key, typename _Tp, typename _Allocator,
715  typename = _RequireAllocator<_Allocator>>
716  unordered_map(initializer_list<pair<_Key, _Tp>>, _Allocator)
717  -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>;
718 
719  template<typename _Key, typename _Tp, typename _Hash, typename _Allocator,
720  typename = _RequireNotAllocatorOrIntegral<_Hash>,
721  typename = _RequireAllocator<_Allocator>>
722  unordered_map(initializer_list<pair<_Key, _Tp>>,
723  typename unordered_map<int, int>::size_type,
724  _Hash, _Allocator)
725  -> unordered_map<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>;
726 
727 #endif
728 
729  template<typename _Key, typename _Tp, typename _Hash,
730  typename _Pred, typename _Alloc>
731  inline void
732  swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
733  unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
734  noexcept(noexcept(__x.swap(__y)))
735  { __x.swap(__y); }
736 
737  template<typename _Key, typename _Tp, typename _Hash,
738  typename _Pred, typename _Alloc>
739  inline bool
740  operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
741  const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
742  { return __x._M_base() == __y._M_base(); }
743 
744 #if __cpp_impl_three_way_comparison < 201907L
745  template<typename _Key, typename _Tp, typename _Hash,
746  typename _Pred, typename _Alloc>
747  inline bool
748  operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
749  const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
750  { return !(__x == __y); }
751 #endif
752 
753  /// Class std::unordered_multimap with safety/checking/debug instrumentation.
754  template<typename _Key, typename _Tp,
755  typename _Hash = std::hash<_Key>,
756  typename _Pred = std::equal_to<_Key>,
757  typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
758  class unordered_multimap
760  unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
761  __gnu_debug::_Safe_unordered_container>,
762  public _GLIBCXX_STD_C::unordered_multimap<
763  _Key, _Tp, _Hash, _Pred, _Alloc>
764  {
765  typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
766  _Pred, _Alloc> _Base;
767  typedef __gnu_debug::_Safe_container<unordered_multimap,
769  typedef typename _Base::const_iterator _Base_const_iterator;
770  typedef typename _Base::iterator _Base_iterator;
771  typedef typename _Base::const_local_iterator _Base_const_local_iterator;
772  typedef typename _Base::local_iterator _Base_local_iterator;
773 
774  template<typename _ItT, typename _SeqT, typename _CatT>
775  friend class ::__gnu_debug::_Safe_iterator;
776  template<typename _ItT, typename _SeqT>
777  friend class ::__gnu_debug::_Safe_local_iterator;
778 
779  public:
780  typedef typename _Base::size_type size_type;
781  typedef typename _Base::hasher hasher;
782  typedef typename _Base::key_equal key_equal;
783  typedef typename _Base::allocator_type allocator_type;
784 
785  typedef typename _Base::key_type key_type;
786  typedef typename _Base::value_type value_type;
787 
789  _Base_iterator, unordered_multimap> iterator;
791  _Base_const_iterator, unordered_multimap> const_iterator;
793  _Base_local_iterator, unordered_multimap> local_iterator;
795  _Base_const_local_iterator, unordered_multimap> const_local_iterator;
796 
797  unordered_multimap() = default;
798 
799  explicit
800  unordered_multimap(size_type __n,
801  const hasher& __hf = hasher(),
802  const key_equal& __eql = key_equal(),
803  const allocator_type& __a = allocator_type())
804  : _Base(__n, __hf, __eql, __a) { }
805 
806  template<typename _InputIterator>
807  unordered_multimap(_InputIterator __first, _InputIterator __last,
808  size_type __n = 0,
809  const hasher& __hf = hasher(),
810  const key_equal& __eql = key_equal(),
811  const allocator_type& __a = allocator_type())
812  : _Base(__gnu_debug::__base(
813  __glibcxx_check_valid_constructor_range(__first, __last)),
814  __gnu_debug::__base(__last), __n,
815  __hf, __eql, __a) { }
816 
817  unordered_multimap(const unordered_multimap&) = default;
818 
819  unordered_multimap(const _Base& __x)
820  : _Base(__x) { }
821 
822  unordered_multimap(unordered_multimap&&) = default;
823 
824  explicit
825  unordered_multimap(const allocator_type& __a)
826  : _Base(__a) { }
827 
828  unordered_multimap(const unordered_multimap& __umap,
829  const allocator_type& __a)
830  : _Base(__umap, __a) { }
831 
832  unordered_multimap(unordered_multimap&& __umap,
833  const allocator_type& __a)
834  : _Safe(std::move(__umap._M_safe()), __a),
835  _Base(std::move(__umap._M_base()), __a) { }
836 
837  unordered_multimap(initializer_list<value_type> __l,
838  size_type __n = 0,
839  const hasher& __hf = hasher(),
840  const key_equal& __eql = key_equal(),
841  const allocator_type& __a = allocator_type())
842  : _Base(__l, __n, __hf, __eql, __a) { }
843 
844  unordered_multimap(size_type __n, const allocator_type& __a)
845  : unordered_multimap(__n, hasher(), key_equal(), __a)
846  { }
847 
848  unordered_multimap(size_type __n, const hasher& __hf,
849  const allocator_type& __a)
850  : unordered_multimap(__n, __hf, key_equal(), __a)
851  { }
852 
853  template<typename _InputIterator>
854  unordered_multimap(_InputIterator __first, _InputIterator __last,
855  size_type __n,
856  const allocator_type& __a)
857  : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a)
858  { }
859 
860  template<typename _InputIterator>
861  unordered_multimap(_InputIterator __first, _InputIterator __last,
862  size_type __n, const hasher& __hf,
863  const allocator_type& __a)
864  : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a)
865  { }
866 
867  unordered_multimap(initializer_list<value_type> __l,
868  size_type __n,
869  const allocator_type& __a)
870  : unordered_multimap(__l, __n, hasher(), key_equal(), __a)
871  { }
872 
873  unordered_multimap(initializer_list<value_type> __l,
874  size_type __n, const hasher& __hf,
875  const allocator_type& __a)
876  : unordered_multimap(__l, __n, __hf, key_equal(), __a)
877  { }
878 
879  ~unordered_multimap() = default;
880 
881  unordered_multimap&
882  operator=(const unordered_multimap&) = default;
883 
884  unordered_multimap&
885  operator=(unordered_multimap&&) = default;
886 
887  unordered_multimap&
888  operator=(initializer_list<value_type> __l)
889  {
890  this->_M_base() = __l;
891  this->_M_invalidate_all();
892  return *this;
893  }
894 
895  void
896  swap(unordered_multimap& __x)
897  noexcept( noexcept(declval<_Base&>().swap(__x)) )
898  {
899  _Safe::_M_swap(__x);
900  _Base::swap(__x);
901  }
902 
903  void
904  clear() noexcept
905  {
906  _Base::clear();
907  this->_M_invalidate_all();
908  }
909 
910  iterator
911  begin() noexcept
912  { return { _Base::begin(), this }; }
913 
914  const_iterator
915  begin() const noexcept
916  { return { _Base::begin(), this }; }
917 
918  iterator
919  end() noexcept
920  { return { _Base::end(), this }; }
921 
922  const_iterator
923  end() const noexcept
924  { return { _Base::end(), this }; }
925 
926  const_iterator
927  cbegin() const noexcept
928  { return { _Base::cbegin(), this }; }
929 
930  const_iterator
931  cend() const noexcept
932  { return { _Base::cend(), this }; }
933 
934  // local versions
935  local_iterator
936  begin(size_type __b)
937  {
938  __glibcxx_check_bucket_index(__b);
939  return { _Base::begin(__b), this };
940  }
941 
942  local_iterator
943  end(size_type __b)
944  {
945  __glibcxx_check_bucket_index(__b);
946  return { _Base::end(__b), this };
947  }
948 
949  const_local_iterator
950  begin(size_type __b) const
951  {
952  __glibcxx_check_bucket_index(__b);
953  return { _Base::begin(__b), this };
954  }
955 
956  const_local_iterator
957  end(size_type __b) const
958  {
959  __glibcxx_check_bucket_index(__b);
960  return { _Base::end(__b), this };
961  }
962 
963  const_local_iterator
964  cbegin(size_type __b) const
965  {
966  __glibcxx_check_bucket_index(__b);
967  return { _Base::cbegin(__b), this };
968  }
969 
970  const_local_iterator
971  cend(size_type __b) const
972  {
973  __glibcxx_check_bucket_index(__b);
974  return { _Base::cend(__b), this };
975  }
976 
977  size_type
978  bucket_size(size_type __b) const
979  {
980  __glibcxx_check_bucket_index(__b);
981  return _Base::bucket_size(__b);
982  }
983 
984  float
985  max_load_factor() const noexcept
986  { return _Base::max_load_factor(); }
987 
988  void
989  max_load_factor(float __f)
990  {
991  __glibcxx_check_max_load_factor(__f);
992  _Base::max_load_factor(__f);
993  }
994 
995  template<typename... _Args>
996  iterator
997  emplace(_Args&&... __args)
998  {
999  size_type __bucket_count = this->bucket_count();
1000  auto __it = _Base::emplace(std::forward<_Args>(__args)...);
1001  _M_check_rehashed(__bucket_count);
1002  return { __it, this };
1003  }
1004 
1005  template<typename... _Args>
1006  iterator
1007  emplace_hint(const_iterator __hint, _Args&&... __args)
1008  {
1009  __glibcxx_check_insert(__hint);
1010  size_type __bucket_count = this->bucket_count();
1011  auto __it = _Base::emplace_hint(__hint.base(),
1012  std::forward<_Args>(__args)...);
1013  _M_check_rehashed(__bucket_count);
1014  return { __it, this };
1015  }
1016 
1017  iterator
1018  insert(const value_type& __obj)
1019  {
1020  size_type __bucket_count = this->bucket_count();
1021  auto __it = _Base::insert(__obj);
1022  _M_check_rehashed(__bucket_count);
1023  return { __it, this };
1024  }
1025 
1026  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1027  // 2354. Unnecessary copying when inserting into maps with braced-init
1028  iterator
1029  insert(value_type&& __x)
1030  {
1031  size_type __bucket_count = this->bucket_count();
1032  auto __it = _Base::insert(std::move(__x));
1033  _M_check_rehashed(__bucket_count);
1034  return { __it, this };
1035  }
1036 
1037  iterator
1038  insert(const_iterator __hint, const value_type& __obj)
1039  {
1040  __glibcxx_check_insert(__hint);
1041  size_type __bucket_count = this->bucket_count();
1042  auto __it = _Base::insert(__hint.base(), __obj);
1043  _M_check_rehashed(__bucket_count);
1044  return { __it, this };
1045  }
1046 
1047  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1048  // 2354. Unnecessary copying when inserting into maps with braced-init
1049  iterator
1050  insert(const_iterator __hint, value_type&& __x)
1051  {
1052  __glibcxx_check_insert(__hint);
1053  size_type __bucket_count = this->bucket_count();
1054  auto __it = _Base::insert(__hint.base(), std::move(__x));
1055  _M_check_rehashed(__bucket_count);
1056  return { __it, this };
1057  }
1058 
1059  template<typename _Pair, typename = typename
1061  _Pair&&>::value>::type>
1062  iterator
1063  insert(_Pair&& __obj)
1064  {
1065  size_type __bucket_count = this->bucket_count();
1066  auto __it = _Base::insert(std::forward<_Pair>(__obj));
1067  _M_check_rehashed(__bucket_count);
1068  return { __it, this };
1069  }
1070 
1071  template<typename _Pair, typename = typename
1073  _Pair&&>::value>::type>
1074  iterator
1075  insert(const_iterator __hint, _Pair&& __obj)
1076  {
1077  __glibcxx_check_insert(__hint);
1078  size_type __bucket_count = this->bucket_count();
1079  auto __it = _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
1080  _M_check_rehashed(__bucket_count);
1081  return { __it, this };
1082  }
1083 
1084  void
1086  { _Base::insert(__l); }
1087 
1088  template<typename _InputIterator>
1089  void
1090  insert(_InputIterator __first, _InputIterator __last)
1091  {
1093  __glibcxx_check_valid_range2(__first, __last, __dist);
1094  size_type __bucket_count = this->bucket_count();
1095 
1096  if (__dist.second >= __gnu_debug::__dp_sign)
1097  _Base::insert(__gnu_debug::__unsafe(__first),
1098  __gnu_debug::__unsafe(__last));
1099  else
1100  _Base::insert(__first, __last);
1101 
1102  _M_check_rehashed(__bucket_count);
1103  }
1104 
1105 #if __cplusplus > 201402L
1106  using node_type = typename _Base::node_type;
1107 
1108  node_type
1109  extract(const_iterator __position)
1110  {
1111  __glibcxx_check_erase(__position);
1112  return _M_extract(__position.base());
1113  }
1114 
1115  node_type
1116  extract(const key_type& __key)
1117  {
1118  const auto __position = _Base::find(__key);
1119  if (__position != _Base::end())
1120  return _M_extract(__position);
1121  return {};
1122  }
1123 
1124  iterator
1125  insert(node_type&& __nh)
1126  { return { _Base::insert(std::move(__nh)), this }; }
1127 
1128  iterator
1129  insert(const_iterator __hint, node_type&& __nh)
1130  {
1131  __glibcxx_check_insert(__hint);
1132  return { _Base::insert(__hint.base(), std::move(__nh)), this };
1133  }
1134 
1135  using _Base::merge;
1136 #endif // C++17
1137 
1138  iterator
1139  find(const key_type& __key)
1140  { return { _Base::find(__key), this }; }
1141 
1142  const_iterator
1143  find(const key_type& __key) const
1144  { return { _Base::find(__key), this }; }
1145 
1147  equal_range(const key_type& __key)
1148  {
1149  auto __res = _Base::equal_range(__key);
1150  return { { __res.first, this }, { __res.second, this } };
1151  }
1152 
1154  equal_range(const key_type& __key) const
1155  {
1156  auto __res = _Base::equal_range(__key);
1157  return { { __res.first, this }, { __res.second, this } };
1158  }
1159 
1160  size_type
1161  erase(const key_type& __key)
1162  {
1163  size_type __ret(0);
1164  size_type __bucket_count = this->bucket_count();
1165  auto __pair = _Base::equal_range(__key);
1166  for (auto __victim = __pair.first; __victim != __pair.second;)
1167  {
1168  _M_invalidate(__victim);
1169  __victim = _Base::erase(__victim);
1170  ++__ret;
1171  }
1172 
1173  _M_check_rehashed(__bucket_count);
1174  return __ret;
1175  }
1176 
1177  iterator
1178  erase(const_iterator __it)
1179  {
1180  __glibcxx_check_erase(__it);
1181  return { _M_erase(__it.base()), this };
1182  }
1183 
1184  iterator
1185  erase(iterator __it)
1186  {
1187  __glibcxx_check_erase(__it);
1188  return { _M_erase(__it.base()), this };
1189  }
1190 
1191  iterator
1192  erase(const_iterator __first, const_iterator __last)
1193  {
1194  __glibcxx_check_erase_range(__first, __last);
1195  for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp)
1196  {
1197  _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(),
1198  _M_message(__gnu_debug::__msg_valid_range)
1199  ._M_iterator(__first, "first")
1200  ._M_iterator(__last, "last"));
1201  _M_invalidate(__tmp);
1202  }
1203 
1204  size_type __bucket_count = this->bucket_count();
1205  auto __next = _Base::erase(__first.base(), __last.base());
1206  _M_check_rehashed(__bucket_count);
1207  return { __next, this };
1208  }
1209 
1210  _Base&
1211  _M_base() noexcept { return *this; }
1212 
1213  const _Base&
1214  _M_base() const noexcept { return *this; }
1215 
1216  private:
1217  void
1218  _M_check_rehashed(size_type __prev_count)
1219  {
1220  if (__prev_count != this->bucket_count())
1221  this->_M_invalidate_all();
1222  }
1223 
1224  void
1225  _M_invalidate(_Base_const_iterator __victim)
1226  {
1227  this->_M_invalidate_if(
1228  [__victim](_Base_const_iterator __it) { return __it == __victim; });
1229  this->_M_invalidate_local_if(
1230  [__victim](_Base_const_local_iterator __it)
1231  { return __it._M_curr() == __victim._M_cur; });
1232  }
1233 
1234  _Base_iterator
1235  _M_erase(_Base_const_iterator __victim)
1236  {
1237  _M_invalidate(__victim);
1238  size_type __bucket_count = this->bucket_count();
1239  _Base_iterator __next = _Base::erase(__victim);
1240  _M_check_rehashed(__bucket_count);
1241  return __next;
1242  }
1243 
1244 #if __cplusplus > 201402L
1245  node_type
1246  _M_extract(_Base_const_iterator __victim)
1247  {
1248  _M_invalidate(__victim);
1249  return _Base::extract(__victim);
1250  }
1251 #endif
1252  };
1253 
1254 #if __cpp_deduction_guides >= 201606
1255 
1256  template<typename _InputIterator,
1257  typename _Hash = hash<__iter_key_t<_InputIterator>>,
1258  typename _Pred = equal_to<__iter_key_t<_InputIterator>>,
1259  typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>,
1260  typename = _RequireInputIter<_InputIterator>,
1261  typename = _RequireNotAllocatorOrIntegral<_Hash>,
1262  typename = _RequireNotAllocator<_Pred>,
1263  typename = _RequireAllocator<_Allocator>>
1264  unordered_multimap(_InputIterator, _InputIterator,
1265  unordered_multimap<int, int>::size_type = {},
1266  _Hash = _Hash(), _Pred = _Pred(),
1267  _Allocator = _Allocator())
1268  -> unordered_multimap<__iter_key_t<_InputIterator>,
1269  __iter_val_t<_InputIterator>, _Hash, _Pred,
1270  _Allocator>;
1271 
1272  template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
1273  typename _Pred = equal_to<_Key>,
1274  typename _Allocator = allocator<pair<const _Key, _Tp>>,
1275  typename = _RequireNotAllocatorOrIntegral<_Hash>,
1276  typename = _RequireNotAllocator<_Pred>,
1277  typename = _RequireAllocator<_Allocator>>
1278  unordered_multimap(initializer_list<pair<_Key, _Tp>>,
1279  unordered_multimap<int, int>::size_type = {},
1280  _Hash = _Hash(), _Pred = _Pred(),
1281  _Allocator = _Allocator())
1282  -> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Allocator>;
1283 
1284  template<typename _InputIterator, typename _Allocator,
1285  typename = _RequireInputIter<_InputIterator>,
1286  typename = _RequireAllocator<_Allocator>>
1287  unordered_multimap(_InputIterator, _InputIterator,
1288  unordered_multimap<int, int>::size_type, _Allocator)
1289  -> unordered_multimap<__iter_key_t<_InputIterator>,
1290  __iter_val_t<_InputIterator>,
1291  hash<__iter_key_t<_InputIterator>>,
1292  equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
1293 
1294  template<typename _InputIterator, typename _Allocator,
1295  typename = _RequireInputIter<_InputIterator>,
1296  typename = _RequireAllocator<_Allocator>>
1297  unordered_multimap(_InputIterator, _InputIterator, _Allocator)
1298  -> unordered_multimap<__iter_key_t<_InputIterator>,
1299  __iter_val_t<_InputIterator>,
1300  hash<__iter_key_t<_InputIterator>>,
1301  equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
1302 
1303  template<typename _InputIterator, typename _Hash, typename _Allocator,
1304  typename = _RequireInputIter<_InputIterator>,
1305  typename = _RequireNotAllocatorOrIntegral<_Hash>,
1306  typename = _RequireAllocator<_Allocator>>
1307  unordered_multimap(_InputIterator, _InputIterator,
1308  unordered_multimap<int, int>::size_type, _Hash,
1309  _Allocator)
1310  -> unordered_multimap<__iter_key_t<_InputIterator>,
1311  __iter_val_t<_InputIterator>, _Hash,
1312  equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
1313 
1314  template<typename _Key, typename _Tp, typename _Allocator,
1315  typename = _RequireAllocator<_Allocator>>
1316  unordered_multimap(initializer_list<pair<_Key, _Tp>>,
1317  unordered_multimap<int, int>::size_type,
1318  _Allocator)
1319  -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>;
1320 
1321  template<typename _Key, typename _Tp, typename _Allocator,
1322  typename = _RequireAllocator<_Allocator>>
1323  unordered_multimap(initializer_list<pair<_Key, _Tp>>, _Allocator)
1324  -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>;
1325 
1326  template<typename _Key, typename _Tp, typename _Hash, typename _Allocator,
1327  typename = _RequireNotAllocatorOrIntegral<_Hash>,
1328  typename = _RequireAllocator<_Allocator>>
1329  unordered_multimap(initializer_list<pair<_Key, _Tp>>,
1330  unordered_multimap<int, int>::size_type,
1331  _Hash, _Allocator)
1332  -> unordered_multimap<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>;
1333 
1334 #endif
1335 
1336  template<typename _Key, typename _Tp, typename _Hash,
1337  typename _Pred, typename _Alloc>
1338  inline void
1339  swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
1340  unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
1341  noexcept(noexcept(__x.swap(__y)))
1342  { __x.swap(__y); }
1343 
1344  template<typename _Key, typename _Tp, typename _Hash,
1345  typename _Pred, typename _Alloc>
1346  inline bool
1347  operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
1348  const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
1349  { return __x._M_base() == __y._M_base(); }
1350 
1351 #if __cpp_impl_three_way_comparison < 201907L
1352  template<typename _Key, typename _Tp, typename _Hash,
1353  typename _Pred, typename _Alloc>
1354  inline bool
1355  operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
1356  const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
1357  { return !(__x == __y); }
1358 #endif
1359 
1360 } // namespace __debug
1361 } // namespace std
1362 
1363 #endif // C++11
1364 
1365 #endif
_Tp * begin(valarray< _Tp > &__va)
Return an iterator pointing to the first element of the valarray.
Definition: valarray:1214
Safe iterator wrapper.
Definition: debug.h:61
One of the comparison functors.
Definition: stl_function.h:331
Common iterator class.
_Iterator & base() noexcept
Return the underlying iterator.
#define __glibcxx_check_insert(_Position)
Definition: macros.h:150
Class std::unordered_map with safety/checking/debug instrumentation.
constexpr auto cbegin(const _Container &__cont) noexcept(noexcept(std::begin(__cont))) -> decltype(std::begin(__cont))
Return an iterator pointing to the first element of the const container.
Definition: range_access.h:119
is_constructible
Definition: type_traits:906
Define a member typedef type only if a boolean constant is true.
Definition: type_traits:2182
Safe iterator wrapper.
Definition: formatter.h:83
#define __glibcxx_check_erase(_Position)
Definition: macros.h:216
The standard allocator, as per [20.4].
Definition: allocator.h:116
Base class for constructing a safe unordered container type that tracks iterators that reference it...
_T2 second
The second member.
Definition: stl_pair.h:218
constexpr _Iterator __base(_Iterator __it)
Class std::unordered_multimap with safety/checking/debug instrumentation.
Primary class template hash.
Definition: typeindex:110
_Tp * end(valarray< _Tp > &__va)
Return an iterator pointing to one past the last element of the valarray.
Definition: valarray:1234
Safe class dealing with some allocator dependent operations.
#define __glibcxx_check_erase_range(_First, _Last)
Definition: macros.h:244
constexpr auto cend(const _Container &__cont) noexcept(noexcept(std::end(__cont))) -> decltype(std::end(__cont))
Return an iterator pointing to one past the last element of the const container.
Definition: range_access.h:130
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:211
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:101
A standard container composed of unique keys (containing at most one of each key value) that associat...
initializer_list