libstdc++
debug/unordered_map
Go to the documentation of this file.
1 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2019 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>
41  class unordered_map;
42  template<typename _Key, typename _Tp, typename _Hash, typename _Pred,
43  typename _Allocator>
44  class unordered_multimap;
45 } } // namespace std::__debug
46 
47 # include <unordered_map>
48 
49 #include <debug/safe_unordered_container.h>
50 #include <debug/safe_container.h>
51 #include <debug/safe_iterator.h>
52 #include <debug/safe_local_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
64  : public __gnu_debug::_Safe_container<
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;
71  typedef __gnu_debug::_Safe_container<unordered_map,
72  _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
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 
93  typedef __gnu_debug::_Safe_iterator<
94  _Base_iterator, unordered_map> iterator;
95  typedef __gnu_debug::_Safe_iterator<
96  _Base_const_iterator, unordered_map> const_iterator;
97  typedef __gnu_debug::_Safe_local_iterator<
98  _Base_local_iterator, unordered_map> local_iterator;
99  typedef __gnu_debug::_Safe_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>
304  std::pair<iterator, bool>
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 
325  std::pair<iterator, bool>
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
336  std::pair<iterator, bool>
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
346  std::enable_if<std::is_constructible<value_type,
347  _Pair&&>::value>::type>
348  std::pair<iterator, bool>
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
380  std::enable_if<std::is_constructible<value_type,
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
393  insert(std::initializer_list<value_type> __l)
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  {
404  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
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 
543  std::pair<iterator, iterator>
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 
550  std::pair<const_iterator, const_iterator>
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; });
622  this->_M_invalidate_local_if(
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  template<typename _Key, typename _Tp, typename _Hash,
745  typename _Pred, typename _Alloc>
746  inline bool
747  operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
748  const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
749  { return !(__x == __y); }
750 
751 
752  /// Class std::unordered_multimap with safety/checking/debug instrumentation.
753  template<typename _Key, typename _Tp,
754  typename _Hash = std::hash<_Key>,
755  typename _Pred = std::equal_to<_Key>,
756  typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
757  class unordered_multimap
758  : public __gnu_debug::_Safe_container<
759  unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
760  __gnu_debug::_Safe_unordered_container>,
761  public _GLIBCXX_STD_C::unordered_multimap<
762  _Key, _Tp, _Hash, _Pred, _Alloc>
763  {
764  typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
765  _Pred, _Alloc> _Base;
766  typedef __gnu_debug::_Safe_container<unordered_multimap,
767  _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
768  typedef typename _Base::const_iterator _Base_const_iterator;
769  typedef typename _Base::iterator _Base_iterator;
770  typedef typename _Base::const_local_iterator _Base_const_local_iterator;
771  typedef typename _Base::local_iterator _Base_local_iterator;
772 
773  template<typename _ItT, typename _SeqT, typename _CatT>
774  friend class ::__gnu_debug::_Safe_iterator;
775  template<typename _ItT, typename _SeqT>
776  friend class ::__gnu_debug::_Safe_local_iterator;
777 
778  public:
779  typedef typename _Base::size_type size_type;
780  typedef typename _Base::hasher hasher;
781  typedef typename _Base::key_equal key_equal;
782  typedef typename _Base::allocator_type allocator_type;
783 
784  typedef typename _Base::key_type key_type;
785  typedef typename _Base::value_type value_type;
786 
787  typedef __gnu_debug::_Safe_iterator<
788  _Base_iterator, unordered_multimap> iterator;
789  typedef __gnu_debug::_Safe_iterator<
790  _Base_const_iterator, unordered_multimap> const_iterator;
791  typedef __gnu_debug::_Safe_local_iterator<
792  _Base_local_iterator, unordered_multimap> local_iterator;
793  typedef __gnu_debug::_Safe_local_iterator<
794  _Base_const_local_iterator, unordered_multimap> const_local_iterator;
795 
796  unordered_multimap() = default;
797 
798  explicit
799  unordered_multimap(size_type __n,
800  const hasher& __hf = hasher(),
801  const key_equal& __eql = key_equal(),
802  const allocator_type& __a = allocator_type())
803  : _Base(__n, __hf, __eql, __a) { }
804 
805  template<typename _InputIterator>
806  unordered_multimap(_InputIterator __first, _InputIterator __last,
807  size_type __n = 0,
808  const hasher& __hf = hasher(),
809  const key_equal& __eql = key_equal(),
810  const allocator_type& __a = allocator_type())
811  : _Base(__gnu_debug::__base(
812  __glibcxx_check_valid_constructor_range(__first, __last)),
813  __gnu_debug::__base(__last), __n,
814  __hf, __eql, __a) { }
815 
816  unordered_multimap(const unordered_multimap&) = default;
817 
818  unordered_multimap(const _Base& __x)
819  : _Base(__x) { }
820 
821  unordered_multimap(unordered_multimap&&) = default;
822 
823  explicit
824  unordered_multimap(const allocator_type& __a)
825  : _Base(__a) { }
826 
827  unordered_multimap(const unordered_multimap& __umap,
828  const allocator_type& __a)
829  : _Base(__umap, __a) { }
830 
831  unordered_multimap(unordered_multimap&& __umap,
832  const allocator_type& __a)
833  : _Safe(std::move(__umap._M_safe()), __a),
834  _Base(std::move(__umap._M_base()), __a) { }
835 
836  unordered_multimap(initializer_list<value_type> __l,
837  size_type __n = 0,
838  const hasher& __hf = hasher(),
839  const key_equal& __eql = key_equal(),
840  const allocator_type& __a = allocator_type())
841  : _Base(__l, __n, __hf, __eql, __a) { }
842 
843  unordered_multimap(size_type __n, const allocator_type& __a)
844  : unordered_multimap(__n, hasher(), key_equal(), __a)
845  { }
846 
847  unordered_multimap(size_type __n, const hasher& __hf,
848  const allocator_type& __a)
849  : unordered_multimap(__n, __hf, key_equal(), __a)
850  { }
851 
852  template<typename _InputIterator>
853  unordered_multimap(_InputIterator __first, _InputIterator __last,
854  size_type __n,
855  const allocator_type& __a)
856  : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a)
857  { }
858 
859  template<typename _InputIterator>
860  unordered_multimap(_InputIterator __first, _InputIterator __last,
861  size_type __n, const hasher& __hf,
862  const allocator_type& __a)
863  : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a)
864  { }
865 
866  unordered_multimap(initializer_list<value_type> __l,
867  size_type __n,
868  const allocator_type& __a)
869  : unordered_multimap(__l, __n, hasher(), key_equal(), __a)
870  { }
871 
872  unordered_multimap(initializer_list<value_type> __l,
873  size_type __n, const hasher& __hf,
874  const allocator_type& __a)
875  : unordered_multimap(__l, __n, __hf, key_equal(), __a)
876  { }
877 
878  ~unordered_multimap() = default;
879 
880  unordered_multimap&
881  operator=(const unordered_multimap&) = default;
882 
883  unordered_multimap&
884  operator=(unordered_multimap&&) = default;
885 
886  unordered_multimap&
887  operator=(initializer_list<value_type> __l)
888  {
889  this->_M_base() = __l;
890  this->_M_invalidate_all();
891  return *this;
892  }
893 
894  void
895  swap(unordered_multimap& __x)
896  noexcept( noexcept(declval<_Base&>().swap(__x)) )
897  {
898  _Safe::_M_swap(__x);
899  _Base::swap(__x);
900  }
901 
902  void
903  clear() noexcept
904  {
905  _Base::clear();
906  this->_M_invalidate_all();
907  }
908 
909  iterator
910  begin() noexcept
911  { return { _Base::begin(), this }; }
912 
913  const_iterator
914  begin() const noexcept
915  { return { _Base::begin(), this }; }
916 
917  iterator
918  end() noexcept
919  { return { _Base::end(), this }; }
920 
921  const_iterator
922  end() const noexcept
923  { return { _Base::end(), this }; }
924 
925  const_iterator
926  cbegin() const noexcept
927  { return { _Base::cbegin(), this }; }
928 
929  const_iterator
930  cend() const noexcept
931  { return { _Base::cend(), this }; }
932 
933  // local versions
934  local_iterator
935  begin(size_type __b)
936  {
937  __glibcxx_check_bucket_index(__b);
938  return { _Base::begin(__b), this };
939  }
940 
941  local_iterator
942  end(size_type __b)
943  {
944  __glibcxx_check_bucket_index(__b);
945  return { _Base::end(__b), this };
946  }
947 
948  const_local_iterator
949  begin(size_type __b) const
950  {
951  __glibcxx_check_bucket_index(__b);
952  return { _Base::begin(__b), this };
953  }
954 
955  const_local_iterator
956  end(size_type __b) const
957  {
958  __glibcxx_check_bucket_index(__b);
959  return { _Base::end(__b), this };
960  }
961 
962  const_local_iterator
963  cbegin(size_type __b) const
964  {
965  __glibcxx_check_bucket_index(__b);
966  return { _Base::cbegin(__b), this };
967  }
968 
969  const_local_iterator
970  cend(size_type __b) const
971  {
972  __glibcxx_check_bucket_index(__b);
973  return { _Base::cend(__b), this };
974  }
975 
976  size_type
977  bucket_size(size_type __b) const
978  {
979  __glibcxx_check_bucket_index(__b);
980  return _Base::bucket_size(__b);
981  }
982 
983  float
984  max_load_factor() const noexcept
985  { return _Base::max_load_factor(); }
986 
987  void
988  max_load_factor(float __f)
989  {
990  __glibcxx_check_max_load_factor(__f);
991  _Base::max_load_factor(__f);
992  }
993 
994  template<typename... _Args>
995  iterator
996  emplace(_Args&&... __args)
997  {
998  size_type __bucket_count = this->bucket_count();
999  auto __it = _Base::emplace(std::forward<_Args>(__args)...);
1000  _M_check_rehashed(__bucket_count);
1001  return { __it, this };
1002  }
1003 
1004  template<typename... _Args>
1005  iterator
1006  emplace_hint(const_iterator __hint, _Args&&... __args)
1007  {
1008  __glibcxx_check_insert(__hint);
1009  size_type __bucket_count = this->bucket_count();
1010  auto __it = _Base::emplace_hint(__hint.base(),
1011  std::forward<_Args>(__args)...);
1012  _M_check_rehashed(__bucket_count);
1013  return { __it, this };
1014  }
1015 
1016  iterator
1017  insert(const value_type& __obj)
1018  {
1019  size_type __bucket_count = this->bucket_count();
1020  auto __it = _Base::insert(__obj);
1021  _M_check_rehashed(__bucket_count);
1022  return { __it, this };
1023  }
1024 
1025  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1026  // 2354. Unnecessary copying when inserting into maps with braced-init
1027  iterator
1028  insert(value_type&& __x)
1029  {
1030  size_type __bucket_count = this->bucket_count();
1031  auto __it = _Base::insert(std::move(__x));
1032  _M_check_rehashed(__bucket_count);
1033  return { __it, this };
1034  }
1035 
1036  iterator
1037  insert(const_iterator __hint, const value_type& __obj)
1038  {
1039  __glibcxx_check_insert(__hint);
1040  size_type __bucket_count = this->bucket_count();
1041  auto __it = _Base::insert(__hint.base(), __obj);
1042  _M_check_rehashed(__bucket_count);
1043  return { __it, this };
1044  }
1045 
1046  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1047  // 2354. Unnecessary copying when inserting into maps with braced-init
1048  iterator
1049  insert(const_iterator __hint, value_type&& __x)
1050  {
1051  __glibcxx_check_insert(__hint);
1052  size_type __bucket_count = this->bucket_count();
1053  auto __it = _Base::insert(__hint.base(), std::move(__x));
1054  _M_check_rehashed(__bucket_count);
1055  return { __it, this };
1056  }
1057 
1058  template<typename _Pair, typename = typename
1059  std::enable_if<std::is_constructible<value_type,
1060  _Pair&&>::value>::type>
1061  iterator
1062  insert(_Pair&& __obj)
1063  {
1064  size_type __bucket_count = this->bucket_count();
1065  auto __it = _Base::insert(std::forward<_Pair>(__obj));
1066  _M_check_rehashed(__bucket_count);
1067  return { __it, this };
1068  }
1069 
1070  template<typename _Pair, typename = typename
1071  std::enable_if<std::is_constructible<value_type,
1072  _Pair&&>::value>::type>
1073  iterator
1074  insert(const_iterator __hint, _Pair&& __obj)
1075  {
1076  __glibcxx_check_insert(__hint);
1077  size_type __bucket_count = this->bucket_count();
1078  auto __it = _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
1079  _M_check_rehashed(__bucket_count);
1080  return { __it, this };
1081  }
1082 
1083  void
1084  insert(std::initializer_list<value_type> __l)
1085  { _Base::insert(__l); }
1086 
1087  template<typename _InputIterator>
1088  void
1089  insert(_InputIterator __first, _InputIterator __last)
1090  {
1091  typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
1092  __glibcxx_check_valid_range2(__first, __last, __dist);
1093  size_type __bucket_count = this->bucket_count();
1094 
1095  if (__dist.second >= __gnu_debug::__dp_sign)
1096  _Base::insert(__gnu_debug::__unsafe(__first),
1097  __gnu_debug::__unsafe(__last));
1098  else
1099  _Base::insert(__first, __last);
1100 
1101  _M_check_rehashed(__bucket_count);
1102  }
1103 
1104 #if __cplusplus > 201402L
1105  using node_type = typename _Base::node_type;
1106 
1107  node_type
1108  extract(const_iterator __position)
1109  {
1110  __glibcxx_check_erase(__position);
1111  return _M_extract(__position.base());
1112  }
1113 
1114  node_type
1115  extract(const key_type& __key)
1116  {
1117  const auto __position = _Base::find(__key);
1118  if (__position != _Base::end())
1119  return _M_extract(__position);
1120  return {};
1121  }
1122 
1123  iterator
1124  insert(node_type&& __nh)
1125  { return { _Base::insert(std::move(__nh)), this }; }
1126 
1127  iterator
1128  insert(const_iterator __hint, node_type&& __nh)
1129  {
1130  __glibcxx_check_insert(__hint);
1131  return { _Base::insert(__hint.base(), std::move(__nh)), this };
1132  }
1133 
1134  using _Base::merge;
1135 #endif // C++17
1136 
1137  iterator
1138  find(const key_type& __key)
1139  { return { _Base::find(__key), this }; }
1140 
1141  const_iterator
1142  find(const key_type& __key) const
1143  { return { _Base::find(__key), this }; }
1144 
1145  std::pair<iterator, iterator>
1146  equal_range(const key_type& __key)
1147  {
1148  auto __res = _Base::equal_range(__key);
1149  return { { __res.first, this }, { __res.second, this } };
1150  }
1151 
1152  std::pair<const_iterator, const_iterator>
1153  equal_range(const key_type& __key) const
1154  {
1155  auto __res = _Base::equal_range(__key);
1156  return { { __res.first, this }, { __res.second, this } };
1157  }
1158 
1159  size_type
1160  erase(const key_type& __key)
1161  {
1162  size_type __ret(0);
1163  size_type __bucket_count = this->bucket_count();
1164  auto __pair = _Base::equal_range(__key);
1165  for (auto __victim = __pair.first; __victim != __pair.second;)
1166  {
1167  _M_invalidate(__victim);
1168  __victim = _Base::erase(__victim);
1169  ++__ret;
1170  }
1171 
1172  _M_check_rehashed(__bucket_count);
1173  return __ret;
1174  }
1175 
1176  iterator
1177  erase(const_iterator __it)
1178  {
1179  __glibcxx_check_erase(__it);
1180  return { _M_erase(__it.base()), this };
1181  }
1182 
1183  iterator
1184  erase(iterator __it)
1185  {
1186  __glibcxx_check_erase(__it);
1187  return { _M_erase(__it.base()), this };
1188  }
1189 
1190  iterator
1191  erase(const_iterator __first, const_iterator __last)
1192  {
1193  __glibcxx_check_erase_range(__first, __last);
1194  for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp)
1195  {
1196  _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(),
1197  _M_message(__gnu_debug::__msg_valid_range)
1198  ._M_iterator(__first, "first")
1199  ._M_iterator(__last, "last"));
1200  _M_invalidate(__tmp);
1201  }
1202 
1203  size_type __bucket_count = this->bucket_count();
1204  auto __next = _Base::erase(__first.base(), __last.base());
1205  _M_check_rehashed(__bucket_count);
1206  return { __next, this };
1207  }
1208 
1209  _Base&
1210  _M_base() noexcept { return *this; }
1211 
1212  const _Base&
1213  _M_base() const noexcept { return *this; }
1214 
1215  private:
1216  void
1217  _M_check_rehashed(size_type __prev_count)
1218  {
1219  if (__prev_count != this->bucket_count())
1220  this->_M_invalidate_all();
1221  }
1222 
1223  void
1224  _M_invalidate(_Base_const_iterator __victim)
1225  {
1226  this->_M_invalidate_if(
1227  [__victim](_Base_const_iterator __it) { return __it == __victim; });
1228  this->_M_invalidate_local_if(
1229  [__victim](_Base_const_local_iterator __it)
1230  { return __it._M_curr() == __victim._M_cur; });
1231  }
1232 
1233  _Base_iterator
1234  _M_erase(_Base_const_iterator __victim)
1235  {
1236  _M_invalidate(__victim);
1237  size_type __bucket_count = this->bucket_count();
1238  _Base_iterator __next = _Base::erase(__victim);
1239  _M_check_rehashed(__bucket_count);
1240  return __next;
1241  }
1242 
1243 #if __cplusplus > 201402L
1244  node_type
1245  _M_extract(_Base_const_iterator __victim)
1246  {
1247  _M_invalidate(__victim);
1248  return _Base::extract(__victim);
1249  }
1250 #endif
1251  };
1252 
1253 #if __cpp_deduction_guides >= 201606
1254 
1255  template<typename _InputIterator,
1256  typename _Hash = hash<__iter_key_t<_InputIterator>>,
1257  typename _Pred = equal_to<__iter_key_t<_InputIterator>>,
1258  typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>,
1259  typename = _RequireInputIter<_InputIterator>,
1260  typename = _RequireNotAllocatorOrIntegral<_Hash>,
1261  typename = _RequireNotAllocator<_Pred>,
1262  typename = _RequireAllocator<_Allocator>>
1263  unordered_multimap(_InputIterator, _InputIterator,
1264  unordered_multimap<int, int>::size_type = {},
1265  _Hash = _Hash(), _Pred = _Pred(),
1266  _Allocator = _Allocator())
1267  -> unordered_multimap<__iter_key_t<_InputIterator>,
1268  __iter_val_t<_InputIterator>, _Hash, _Pred,
1269  _Allocator>;
1270 
1271  template<typename _Key, typename _Tp, typename _Hash = hash<_Key>,
1272  typename _Pred = equal_to<_Key>,
1273  typename _Allocator = allocator<pair<const _Key, _Tp>>,
1274  typename = _RequireNotAllocatorOrIntegral<_Hash>,
1275  typename = _RequireNotAllocator<_Pred>,
1276  typename = _RequireAllocator<_Allocator>>
1277  unordered_multimap(initializer_list<pair<_Key, _Tp>>,
1278  unordered_multimap<int, int>::size_type = {},
1279  _Hash = _Hash(), _Pred = _Pred(),
1280  _Allocator = _Allocator())
1281  -> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Allocator>;
1282 
1283  template<typename _InputIterator, typename _Allocator,
1284  typename = _RequireInputIter<_InputIterator>,
1285  typename = _RequireAllocator<_Allocator>>
1286  unordered_multimap(_InputIterator, _InputIterator,
1287  unordered_multimap<int, int>::size_type, _Allocator)
1288  -> unordered_multimap<__iter_key_t<_InputIterator>,
1289  __iter_val_t<_InputIterator>,
1290  hash<__iter_key_t<_InputIterator>>,
1291  equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
1292 
1293  template<typename _InputIterator, typename _Allocator,
1294  typename = _RequireInputIter<_InputIterator>,
1295  typename = _RequireAllocator<_Allocator>>
1296  unordered_multimap(_InputIterator, _InputIterator, _Allocator)
1297  -> unordered_multimap<__iter_key_t<_InputIterator>,
1298  __iter_val_t<_InputIterator>,
1299  hash<__iter_key_t<_InputIterator>>,
1300  equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
1301 
1302  template<typename _InputIterator, typename _Hash, typename _Allocator,
1303  typename = _RequireInputIter<_InputIterator>,
1304  typename = _RequireNotAllocatorOrIntegral<_Hash>,
1305  typename = _RequireAllocator<_Allocator>>
1306  unordered_multimap(_InputIterator, _InputIterator,
1307  unordered_multimap<int, int>::size_type, _Hash,
1308  _Allocator)
1309  -> unordered_multimap<__iter_key_t<_InputIterator>,
1310  __iter_val_t<_InputIterator>, _Hash,
1311  equal_to<__iter_key_t<_InputIterator>>, _Allocator>;
1312 
1313  template<typename _Key, typename _Tp, typename _Allocator,
1314  typename = _RequireAllocator<_Allocator>>
1315  unordered_multimap(initializer_list<pair<_Key, _Tp>>,
1316  unordered_multimap<int, int>::size_type,
1317  _Allocator)
1318  -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>;
1319 
1320  template<typename _Key, typename _Tp, typename _Allocator,
1321  typename = _RequireAllocator<_Allocator>>
1322  unordered_multimap(initializer_list<pair<_Key, _Tp>>, _Allocator)
1323  -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>;
1324 
1325  template<typename _Key, typename _Tp, typename _Hash, typename _Allocator,
1326  typename = _RequireNotAllocatorOrIntegral<_Hash>,
1327  typename = _RequireAllocator<_Allocator>>
1328  unordered_multimap(initializer_list<pair<_Key, _Tp>>,
1329  unordered_multimap<int, int>::size_type,
1330  _Hash, _Allocator)
1331  -> unordered_multimap<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>;
1332 
1333 #endif
1334 
1335  template<typename _Key, typename _Tp, typename _Hash,
1336  typename _Pred, typename _Alloc>
1337  inline void
1338  swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
1339  unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
1340  noexcept(noexcept(__x.swap(__y)))
1341  { __x.swap(__y); }
1342 
1343  template<typename _Key, typename _Tp, typename _Hash,
1344  typename _Pred, typename _Alloc>
1345  inline bool
1346  operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
1347  const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
1348  { return __x._M_base() == __y._M_base(); }
1349 
1350  template<typename _Key, typename _Tp, typename _Hash,
1351  typename _Pred, typename _Alloc>
1352  inline bool
1353  operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
1354  const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
1355  { return !(__x == __y); }
1356 
1357 } // namespace __debug
1358 } // namespace std
1359 
1360 #endif // C++11
1361 
1362 #endif