]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/debug/unordered_set
re PR c++/83116 (Statement with no effect causes wrong code of static object constexp...
[thirdparty/gcc.git] / libstdc++-v3 / include / debug / unordered_set
CommitLineData
e63637ea
BK
1// Debugging unordered_set/unordered_multiset implementation -*- C++ -*-
2
cbe34bb5 3// Copyright (C) 2003-2017 Free Software Foundation, Inc.
e63637ea
BK
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
748086b7 8// Free Software Foundation; either version 3, or (at your option)
e63637ea
BK
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
748086b7
JJ
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/>.
e63637ea
BK
24
25/** @file debug/unordered_set
26 * This file is a GNU debug extension to the Standard C++ Library.
27 */
28
29#ifndef _GLIBCXX_DEBUG_UNORDERED_SET
30#define _GLIBCXX_DEBUG_UNORDERED_SET 1
31
541a9b10
JW
32#pragma GCC system_header
33
734f5023 34#if __cplusplus < 201103L
ab65a4c7 35# include <bits/c++0x_warning.h>
c878d6ba
PC
36#else
37# include <unordered_set>
e63637ea 38
364c862b 39#include <debug/safe_unordered_container.h>
15ee1a77 40#include <debug/safe_container.h>
e63637ea 41#include <debug/safe_iterator.h>
77e0bf4e 42#include <debug/safe_local_iterator.h>
e63637ea 43
12ffa228 44namespace std _GLIBCXX_VISIBILITY(default)
e63637ea
BK
45{
46namespace __debug
47{
1ceb9e06 48 /// Class std::unordered_set with safety/checking/debug instrumentation.
e63637ea 49 template<typename _Value,
ced3cb9f 50 typename _Hash = std::hash<_Value>,
e63637ea 51 typename _Pred = std::equal_to<_Value>,
ced3cb9f 52 typename _Alloc = std::allocator<_Value> >
e63637ea 53 class unordered_set
15ee1a77
FD
54 : public __gnu_debug::_Safe_container<
55 unordered_set<_Value, _Hash, _Pred, _Alloc>, _Alloc,
56 __gnu_debug::_Safe_unordered_container>,
57 public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>
e63637ea 58 {
15ee1a77
FD
59 typedef _GLIBCXX_STD_C::unordered_set<
60 _Value, _Hash, _Pred, _Alloc> _Base;
61 typedef __gnu_debug::_Safe_container<
62 unordered_set, _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
63
64 typedef typename _Base::const_iterator _Base_const_iterator;
65 typedef typename _Base::iterator _Base_iterator;
77e0bf4e 66 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
15ee1a77 67 typedef typename _Base::local_iterator _Base_local_iterator;
e63637ea
BK
68
69 public:
15ee1a77
FD
70 typedef typename _Base::size_type size_type;
71 typedef typename _Base::hasher hasher;
72 typedef typename _Base::key_equal key_equal;
73 typedef typename _Base::allocator_type allocator_type;
74
75 typedef typename _Base::key_type key_type;
76 typedef typename _Base::value_type value_type;
77
78 typedef __gnu_debug::_Safe_iterator<
79 _Base_iterator, unordered_set> iterator;
80 typedef __gnu_debug::_Safe_iterator<
81 _Base_const_iterator, unordered_set> const_iterator;
82 typedef __gnu_debug::_Safe_local_iterator<
83 _Base_local_iterator, unordered_set> local_iterator;
84 typedef __gnu_debug::_Safe_local_iterator<
85 _Base_const_local_iterator, unordered_set> const_local_iterator;
e63637ea 86
da27f556
FD
87 unordered_set() = default;
88
e63637ea 89 explicit
da27f556 90 unordered_set(size_type __n,
e63637ea
BK
91 const hasher& __hf = hasher(),
92 const key_equal& __eql = key_equal(),
93 const allocator_type& __a = allocator_type())
ced3cb9f 94 : _Base(__n, __hf, __eql, __a) { }
e63637ea
BK
95
96 template<typename _InputIterator>
15ee1a77 97 unordered_set(_InputIterator __first, _InputIterator __last,
417e896e 98 size_type __n = 0,
15ee1a77
FD
99 const hasher& __hf = hasher(),
100 const key_equal& __eql = key_equal(),
e63637ea 101 const allocator_type& __a = allocator_type())
1f5ca1a1
PC
102 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
103 __last)),
104 __gnu_debug::__base(__last), __n,
4c2d93db 105 __hf, __eql, __a) { }
ced3cb9f 106
0462b6aa 107 unordered_set(const unordered_set&) = default;
ced3cb9f 108
0462b6aa 109 unordered_set(const _Base& __x)
15ee1a77 110 : _Base(__x) { }
0462b6aa
FD
111
112 unordered_set(unordered_set&&) = default;
113
114 explicit
115 unordered_set(const allocator_type& __a)
15ee1a77 116 : _Base(__a) { }
0462b6aa
FD
117
118 unordered_set(const unordered_set& __uset,
119 const allocator_type& __a)
15ee1a77 120 : _Base(__uset, __a) { }
ced3cb9f 121
0462b6aa
FD
122 unordered_set(unordered_set&& __uset,
123 const allocator_type& __a)
15ee1a77
FD
124 : _Safe(std::move(__uset._M_safe()), __a),
125 _Base(std::move(__uset._M_base()), __a) { }
e63637ea 126
988499f4 127 unordered_set(initializer_list<value_type> __l,
417e896e 128 size_type __n = 0,
988499f4
JM
129 const hasher& __hf = hasher(),
130 const key_equal& __eql = key_equal(),
131 const allocator_type& __a = allocator_type())
4c2d93db 132 : _Base(__l, __n, __hf, __eql, __a) { }
e63637ea 133
e55b80f5
FD
134 unordered_set(size_type __n, const allocator_type& __a)
135 : unordered_set(__n, hasher(), key_equal(), __a)
136 { }
137
138 unordered_set(size_type __n, const hasher& __hf,
139 const allocator_type& __a)
140 : unordered_set(__n, __hf, key_equal(), __a)
141 { }
142
143 template<typename _InputIterator>
144 unordered_set(_InputIterator __first, _InputIterator __last,
145 size_type __n,
146 const allocator_type& __a)
147 : unordered_set(__first, __last, __n, hasher(), key_equal(), __a)
148 { }
149
150 template<typename _InputIterator>
151 unordered_set(_InputIterator __first, _InputIterator __last,
152 size_type __n, const hasher& __hf,
153 const allocator_type& __a)
154 : unordered_set(__first, __last, __n, __hf, key_equal(), __a)
155 { }
156
157 unordered_set(initializer_list<value_type> __l,
158 size_type __n,
159 const allocator_type& __a)
160 : unordered_set(__l, __n, hasher(), key_equal(), __a)
161 { }
162
163 unordered_set(initializer_list<value_type> __l,
164 size_type __n, const hasher& __hf,
165 const allocator_type& __a)
166 : unordered_set(__l, __n, __hf, key_equal(), __a)
167 { }
168
15ee1a77 169 ~unordered_set() = default;
6f59ea25 170
ced3cb9f 171 unordered_set&
15ee1a77 172 operator=(const unordered_set&) = default;
69b3331e
PC
173
174 unordered_set&
15ee1a77 175 operator=(unordered_set&&) = default;
69b3331e 176
988499f4
JM
177 unordered_set&
178 operator=(initializer_list<value_type> __l)
179 {
0462b6aa
FD
180 _M_base() = __l;
181 this->_M_invalidate_all();
988499f4
JM
182 return *this;
183 }
184
e63637ea 185 void
ff74fd13 186 swap(unordered_set& __x)
c5d9ec56 187 noexcept( noexcept(declval<_Base&>().swap(__x)) )
e63637ea 188 {
15ee1a77 189 _Safe::_M_swap(__x);
ced3cb9f 190 _Base::swap(__x);
e63637ea 191 }
69b3331e
PC
192
193 void
d3677132 194 clear() noexcept
69b3331e
PC
195 {
196 _Base::clear();
197 this->_M_invalidate_all();
198 }
199
15ee1a77 200 iterator
d3677132 201 begin() noexcept
ced3cb9f
PC
202 { return iterator(_Base::begin(), this); }
203
204 const_iterator
d3677132 205 begin() const noexcept
ced3cb9f
PC
206 { return const_iterator(_Base::begin(), this); }
207
208 iterator
d3677132 209 end() noexcept
ced3cb9f
PC
210 { return iterator(_Base::end(), this); }
211
212 const_iterator
d3677132 213 end() const noexcept
ced3cb9f
PC
214 { return const_iterator(_Base::end(), this); }
215
216 const_iterator
d3677132 217 cbegin() const noexcept
ced3cb9f
PC
218 { return const_iterator(_Base::begin(), this); }
219
220 const_iterator
d3677132 221 cend() const noexcept
ced3cb9f
PC
222 { return const_iterator(_Base::end(), this); }
223
224 // local versions
77e0bf4e
FD
225 local_iterator
226 begin(size_type __b)
7181e991
FD
227 {
228 __glibcxx_check_bucket_index(__b);
2e5189c8 229 return local_iterator(_Base::begin(__b), this);
7181e991 230 }
77e0bf4e
FD
231
232 local_iterator
233 end(size_type __b)
7181e991
FD
234 {
235 __glibcxx_check_bucket_index(__b);
2e5189c8 236 return local_iterator(_Base::end(__b), this);
7181e991 237 }
77e0bf4e
FD
238
239 const_local_iterator
240 begin(size_type __b) const
7181e991
FD
241 {
242 __glibcxx_check_bucket_index(__b);
2e5189c8 243 return const_local_iterator(_Base::begin(__b), this);
7181e991 244 }
77e0bf4e
FD
245
246 const_local_iterator
247 end(size_type __b) const
7181e991
FD
248 {
249 __glibcxx_check_bucket_index(__b);
2e5189c8 250 return const_local_iterator(_Base::end(__b), this);
7181e991 251 }
77e0bf4e
FD
252
253 const_local_iterator
254 cbegin(size_type __b) const
7181e991
FD
255 {
256 __glibcxx_check_bucket_index(__b);
2e5189c8 257 return const_local_iterator(_Base::cbegin(__b), this);
7181e991 258 }
77e0bf4e
FD
259
260 const_local_iterator
261 cend(size_type __b) const
7181e991
FD
262 {
263 __glibcxx_check_bucket_index(__b);
2e5189c8 264 return const_local_iterator(_Base::cend(__b), this);
7181e991
FD
265 }
266
267 size_type
268 bucket_size(size_type __b) const
269 {
270 __glibcxx_check_bucket_index(__b);
271 return _Base::bucket_size(__b);
272 }
ced3cb9f 273
14cbb5d8
FD
274 float
275 max_load_factor() const noexcept
276 { return _Base::max_load_factor(); }
277
278 void
279 max_load_factor(float __f)
280 {
281 __glibcxx_check_max_load_factor(__f);
282 _Base::max_load_factor(__f);
283 }
284
9b81593b
FD
285 template<typename... _Args>
286 std::pair<iterator, bool>
287 emplace(_Args&&... __args)
288 {
289 size_type __bucket_count = this->bucket_count();
290 std::pair<_Base_iterator, bool> __res
291 = _Base::emplace(std::forward<_Args>(__args)...);
292 _M_check_rehashed(__bucket_count);
293 return std::make_pair(iterator(__res.first, this), __res.second);
294 }
295
296 template<typename... _Args>
297 iterator
298 emplace_hint(const_iterator __hint, _Args&&... __args)
299 {
300 __glibcxx_check_insert(__hint);
301 size_type __bucket_count = this->bucket_count();
302 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
303 std::forward<_Args>(__args)...);
304 _M_check_rehashed(__bucket_count);
305 return iterator(__it, this);
306 }
307
ced3cb9f
PC
308 std::pair<iterator, bool>
309 insert(const value_type& __obj)
310 {
77e0bf4e 311 size_type __bucket_count = this->bucket_count();
15ee1a77
FD
312 std::pair<_Base_iterator, bool> __res
313 = _Base::insert(__obj);
77e0bf4e 314 _M_check_rehashed(__bucket_count);
ced3cb9f
PC
315 return std::make_pair(iterator(__res.first, this), __res.second);
316 }
317
318 iterator
d66411ba 319 insert(const_iterator __hint, const value_type& __obj)
ced3cb9f 320 {
d66411ba 321 __glibcxx_check_insert(__hint);
77e0bf4e
FD
322 size_type __bucket_count = this->bucket_count();
323 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
324 _M_check_rehashed(__bucket_count);
325 return iterator(__it, this);
ced3cb9f
PC
326 }
327
fb7342fd
PC
328 std::pair<iterator, bool>
329 insert(value_type&& __obj)
330 {
77e0bf4e 331 size_type __bucket_count = this->bucket_count();
15ee1a77
FD
332 std::pair<_Base_iterator, bool> __res
333 = _Base::insert(std::move(__obj));
77e0bf4e 334 _M_check_rehashed(__bucket_count);
fb7342fd
PC
335 return std::make_pair(iterator(__res.first, this), __res.second);
336 }
337
338 iterator
d66411ba 339 insert(const_iterator __hint, value_type&& __obj)
fb7342fd 340 {
d66411ba 341 __glibcxx_check_insert(__hint);
77e0bf4e
FD
342 size_type __bucket_count = this->bucket_count();
343 _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj));
344 _M_check_rehashed(__bucket_count);
345 return iterator(__it, this);
fb7342fd
PC
346 }
347
ced3cb9f
PC
348 void
349 insert(std::initializer_list<value_type> __l)
77e0bf4e
FD
350 {
351 size_type __bucket_count = this->bucket_count();
352 _Base::insert(__l);
353 _M_check_rehashed(__bucket_count);
354 }
ced3cb9f
PC
355
356 template<typename _InputIterator>
77e0bf4e
FD
357 void
358 insert(_InputIterator __first, _InputIterator __last)
359 {
24167c42
FD
360 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
361 __glibcxx_check_valid_range2(__first, __last, __dist);
77e0bf4e 362 size_type __bucket_count = this->bucket_count();
24167c42
FD
363
364 if (__dist.second >= __gnu_debug::__dp_sign)
365 _Base::insert(__gnu_debug::__unsafe(__first),
366 __gnu_debug::__unsafe(__last));
367 else
368 _Base::insert(__first, __last);
369
77e0bf4e 370 _M_check_rehashed(__bucket_count);
ced3cb9f
PC
371 }
372
2dbe56bd
JW
373#if __cplusplus > 201402L
374 using node_type = typename _Base::node_type;
375
376 struct insert_return_type
377 {
378 bool inserted;
379 iterator position;
380 node_type node;
381 };
382
383 node_type
384 extract(const_iterator __position)
385 {
386 __glibcxx_check_erase(__position);
387 _Base_const_iterator __victim = __position.base();
388 this->_M_invalidate_if(
389 [__victim](_Base_const_iterator __it) { return __it == __victim; }
390 );
391 this->_M_invalidate_local_if(
392 [__victim](_Base_const_local_iterator __it) {
393 return __it._M_curr() == __victim._M_cur;
394 });
395 return _Base::extract(__position.base());
396 }
397
398 node_type
399 extract(const key_type& __key)
400 {
401 const auto __position = find(__key);
402 if (__position != end())
403 return extract(__position);
404 return {};
405 }
406
407 insert_return_type
408 insert(node_type&& __nh)
409 {
410 auto __ret = _Base::insert(std::move(__nh));
411 iterator __pos = iterator(__ret.position, this);
412 return { __ret.inserted, __pos, std::move(__ret.node) };
413 }
414
415 iterator
416 insert(const_iterator __hint, node_type&& __nh)
417 {
418 __glibcxx_check_insert(__hint);
419 return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
420 }
421
422 using _Base::merge;
423#endif // C++17
424
ced3cb9f
PC
425 iterator
426 find(const key_type& __key)
427 { return iterator(_Base::find(__key), this); }
428
429 const_iterator
430 find(const key_type& __key) const
431 { return const_iterator(_Base::find(__key), this); }
432
433 std::pair<iterator, iterator>
434 equal_range(const key_type& __key)
435 {
15ee1a77
FD
436 std::pair<_Base_iterator, _Base_iterator> __res
437 = _Base::equal_range(__key);
ced3cb9f
PC
438 return std::make_pair(iterator(__res.first, this),
439 iterator(__res.second, this));
440 }
441
442 std::pair<const_iterator, const_iterator>
443 equal_range(const key_type& __key) const
444 {
afe96d41
FD
445 std::pair<_Base_const_iterator, _Base_const_iterator>
446 __res = _Base::equal_range(__key);
ced3cb9f
PC
447 return std::make_pair(const_iterator(__res.first, this),
448 const_iterator(__res.second, this));
449 }
450
451 size_type
452 erase(const key_type& __key)
453 {
454 size_type __ret(0);
afe96d41
FD
455 _Base_iterator __victim(_Base::find(__key));
456 if (__victim != _Base::end())
ced3cb9f 457 {
77e0bf4e
FD
458 this->_M_invalidate_if(
459 [__victim](_Base_const_iterator __it)
460 { return __it == __victim; });
77e0bf4e 461 this->_M_invalidate_local_if(
5b3be7cf 462 [__victim](_Base_const_local_iterator __it)
92e16228 463 { return __it._M_curr() == __victim._M_cur; });
77e0bf4e 464 size_type __bucket_count = this->bucket_count();
afe96d41 465 _Base::erase(__victim);
77e0bf4e 466 _M_check_rehashed(__bucket_count);
ced3cb9f
PC
467 __ret = 1;
468 }
469 return __ret;
470 }
471
d723ced2 472 iterator
ced3cb9f
PC
473 erase(const_iterator __it)
474 {
475 __glibcxx_check_erase(__it);
77e0bf4e
FD
476 _Base_const_iterator __victim = __it.base();
477 this->_M_invalidate_if(
478 [__victim](_Base_const_iterator __it)
479 { return __it == __victim; });
77e0bf4e 480 this->_M_invalidate_local_if(
5b3be7cf 481 [__victim](_Base_const_local_iterator __it)
92e16228 482 { return __it._M_curr() == __victim._M_cur; });
77e0bf4e
FD
483 size_type __bucket_count = this->bucket_count();
484 _Base_iterator __next = _Base::erase(__it.base());
485 _M_check_rehashed(__bucket_count);
486 return iterator(__next, this);
ced3cb9f
PC
487 }
488
6dc88283
PC
489 iterator
490 erase(iterator __it)
491 { return erase(const_iterator(__it)); }
492
d723ced2 493 iterator
ced3cb9f
PC
494 erase(const_iterator __first, const_iterator __last)
495 {
496 __glibcxx_check_erase_range(__first, __last);
afe96d41
FD
497 for (_Base_const_iterator __tmp = __first.base();
498 __tmp != __last.base(); ++__tmp)
499 {
500 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
501 _M_message(__gnu_debug::__msg_valid_range)
502 ._M_iterator(__first, "first")
503 ._M_iterator(__last, "last"));
77e0bf4e
FD
504 this->_M_invalidate_if(
505 [__tmp](_Base_const_iterator __it)
506 { return __it == __tmp; });
77e0bf4e 507 this->_M_invalidate_local_if(
5b3be7cf 508 [__tmp](_Base_const_local_iterator __it)
92e16228 509 { return __it._M_curr() == __tmp._M_cur; });
afe96d41 510 }
77e0bf4e
FD
511 size_type __bucket_count = this->bucket_count();
512 _Base_iterator __next = _Base::erase(__first.base(),
513 __last.base());
514 _M_check_rehashed(__bucket_count);
515 return iterator(__next, this);
ced3cb9f
PC
516 }
517
518 _Base&
15ee1a77 519 _M_base() noexcept { return *this; }
ced3cb9f
PC
520
521 const _Base&
d3677132 522 _M_base() const noexcept { return *this; }
ced3cb9f 523
69b3331e 524 private:
77e0bf4e
FD
525 void
526 _M_check_rehashed(size_type __prev_count)
527 {
528 if (__prev_count != this->bucket_count())
15ee1a77 529 this->_M_invalidate_locals();
69b3331e 530 }
e63637ea
BK
531 };
532
957f5fea
VV
533#if __cpp_deduction_guides >= 201606
534
535 template<typename _InputIterator,
536 typename _Hash =
537 hash<typename iterator_traits<_InputIterator>::value_type>,
538 typename _Pred =
539 equal_to<typename iterator_traits<_InputIterator>::value_type>,
540 typename _Allocator =
541 allocator<typename iterator_traits<_InputIterator>::value_type>,
542 typename = _RequireInputIter<_InputIterator>,
543 typename = _RequireAllocator<_Allocator>>
544 unordered_set(_InputIterator, _InputIterator,
545 unordered_set<int>::size_type = {},
546 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
547 -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
548 _Hash, _Pred, _Allocator>;
549
550 template<typename _Tp, typename _Hash = hash<_Tp>,
551 typename _Pred = equal_to<_Tp>,
552 typename _Allocator = allocator<_Tp>,
553 typename = _RequireAllocator<_Allocator>>
554 unordered_set(initializer_list<_Tp>,
555 unordered_set<int>::size_type = {},
556 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
557 -> unordered_set<_Tp, _Hash, _Pred, _Allocator>;
558
559 template<typename _InputIterator, typename _Allocator,
560 typename = _RequireInputIter<_InputIterator>,
561 typename = _RequireAllocator<_Allocator>>
562 unordered_set(_InputIterator, _InputIterator,
563 unordered_set<int>::size_type, _Allocator)
564 -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
565 hash<
566 typename iterator_traits<_InputIterator>::value_type>,
567 equal_to<
568 typename iterator_traits<_InputIterator>::value_type>,
569 _Allocator>;
570
571 template<typename _InputIterator, typename _Hash, typename _Allocator,
572 typename = _RequireInputIter<_InputIterator>,
573 typename = _RequireAllocator<_Allocator>>
574 unordered_set(_InputIterator, _InputIterator,
575 unordered_set<int>::size_type,
576 _Hash, _Allocator)
577 -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
578 _Hash,
579 equal_to<
580 typename iterator_traits<_InputIterator>::value_type>,
581 _Allocator>;
582
583 template<typename _Tp, typename _Allocator,
584 typename = _RequireAllocator<_Allocator>>
585 unordered_set(initializer_list<_Tp>,
586 unordered_set<int>::size_type, _Allocator)
587 -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
588
589 template<typename _Tp, typename _Hash, typename _Allocator,
590 typename = _RequireAllocator<_Allocator>>
591 unordered_set(initializer_list<_Tp>,
592 unordered_set<int>::size_type, _Hash, _Allocator)
593 -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>;
594
595#endif
596
e63637ea 597 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
69b3331e
PC
598 inline void
599 swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
600 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
c5d9ec56 601 noexcept(noexcept(__x.swap(__y)))
69b3331e 602 { __x.swap(__y); }
e63637ea 603
5dc22714
PC
604 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
605 inline bool
606 operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
607 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
637fd8b3 608 { return __x._M_base() == __y._M_base(); }
5dc22714
PC
609
610 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
611 inline bool
612 operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
613 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
614 { return !(__x == __y); }
615
e63637ea 616
1ceb9e06 617 /// Class std::unordered_multiset with safety/checking/debug instrumentation.
e63637ea 618 template<typename _Value,
ced3cb9f 619 typename _Hash = std::hash<_Value>,
e63637ea 620 typename _Pred = std::equal_to<_Value>,
ced3cb9f 621 typename _Alloc = std::allocator<_Value> >
e63637ea 622 class unordered_multiset
15ee1a77
FD
623 : public __gnu_debug::_Safe_container<
624 unordered_multiset<_Value, _Hash, _Pred, _Alloc>, _Alloc,
625 __gnu_debug::_Safe_unordered_container>,
626 public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>
e63637ea 627 {
15ee1a77
FD
628 typedef _GLIBCXX_STD_C::unordered_multiset<
629 _Value, _Hash, _Pred, _Alloc> _Base;
630 typedef __gnu_debug::_Safe_container<unordered_multiset,
631 _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
632 typedef typename _Base::const_iterator _Base_const_iterator;
633 typedef typename _Base::iterator _Base_iterator;
634 typedef typename _Base::const_local_iterator
635 _Base_const_local_iterator;
636 typedef typename _Base::local_iterator _Base_local_iterator;
0462b6aa 637
e63637ea 638 public:
15ee1a77
FD
639 typedef typename _Base::size_type size_type;
640 typedef typename _Base::hasher hasher;
641 typedef typename _Base::key_equal key_equal;
642 typedef typename _Base::allocator_type allocator_type;
643
644 typedef typename _Base::key_type key_type;
645 typedef typename _Base::value_type value_type;
646
647 typedef __gnu_debug::_Safe_iterator<
648 _Base_iterator, unordered_multiset> iterator;
649 typedef __gnu_debug::_Safe_iterator<
650 _Base_const_iterator, unordered_multiset> const_iterator;
77e0bf4e 651 typedef __gnu_debug::_Safe_local_iterator<
15ee1a77 652 _Base_local_iterator, unordered_multiset> local_iterator;
77e0bf4e
FD
653 typedef __gnu_debug::_Safe_local_iterator<
654 _Base_const_local_iterator, unordered_multiset> const_local_iterator;
e63637ea 655
da27f556
FD
656 unordered_multiset() = default;
657
e63637ea 658 explicit
da27f556 659 unordered_multiset(size_type __n,
ced3cb9f
PC
660 const hasher& __hf = hasher(),
661 const key_equal& __eql = key_equal(),
662 const allocator_type& __a = allocator_type())
663 : _Base(__n, __hf, __eql, __a) { }
e63637ea
BK
664
665 template<typename _InputIterator>
15ee1a77 666 unordered_multiset(_InputIterator __first, _InputIterator __last,
417e896e 667 size_type __n = 0,
15ee1a77
FD
668 const hasher& __hf = hasher(),
669 const key_equal& __eql = key_equal(),
ced3cb9f 670 const allocator_type& __a = allocator_type())
1f5ca1a1
PC
671 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
672 __last)),
673 __gnu_debug::__base(__last), __n,
4c2d93db 674 __hf, __eql, __a) { }
ced3cb9f 675
0462b6aa 676 unordered_multiset(const unordered_multiset&) = default;
ced3cb9f 677
15ee1a77 678 unordered_multiset(const _Base& __x)
4c2d93db 679 : _Base(__x) { }
ced3cb9f 680
0462b6aa
FD
681 unordered_multiset(unordered_multiset&&) = default;
682
683 explicit
684 unordered_multiset(const allocator_type& __a)
15ee1a77 685 : _Base(__a) { }
0462b6aa
FD
686
687 unordered_multiset(const unordered_multiset& __uset,
688 const allocator_type& __a)
15ee1a77
FD
689 : _Base(__uset, __a) { }
690
0462b6aa
FD
691 unordered_multiset(unordered_multiset&& __uset,
692 const allocator_type& __a)
15ee1a77
FD
693 : _Safe(std::move(__uset._M_safe()), __a),
694 _Base(std::move(__uset._M_base()), __a) { }
e63637ea 695
988499f4 696 unordered_multiset(initializer_list<value_type> __l,
417e896e 697 size_type __n = 0,
988499f4
JM
698 const hasher& __hf = hasher(),
699 const key_equal& __eql = key_equal(),
700 const allocator_type& __a = allocator_type())
4c2d93db 701 : _Base(__l, __n, __hf, __eql, __a) { }
e63637ea 702
e55b80f5
FD
703 unordered_multiset(size_type __n, const allocator_type& __a)
704 : unordered_multiset(__n, hasher(), key_equal(), __a)
705 { }
706
707 unordered_multiset(size_type __n, const hasher& __hf,
708 const allocator_type& __a)
709 : unordered_multiset(__n, __hf, key_equal(), __a)
710 { }
711
712 template<typename _InputIterator>
713 unordered_multiset(_InputIterator __first, _InputIterator __last,
714 size_type __n,
715 const allocator_type& __a)
716 : unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a)
717 { }
718
719 template<typename _InputIterator>
720 unordered_multiset(_InputIterator __first, _InputIterator __last,
721 size_type __n, const hasher& __hf,
722 const allocator_type& __a)
723 : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a)
724 { }
725
726 unordered_multiset(initializer_list<value_type> __l,
727 size_type __n,
728 const allocator_type& __a)
729 : unordered_multiset(__l, __n, hasher(), key_equal(), __a)
730 { }
731
732 unordered_multiset(initializer_list<value_type> __l,
733 size_type __n, const hasher& __hf,
734 const allocator_type& __a)
735 : unordered_multiset(__l, __n, __hf, key_equal(), __a)
736 { }
737
15ee1a77 738 ~unordered_multiset() = default;
6f59ea25 739
ced3cb9f 740 unordered_multiset&
15ee1a77 741 operator=(const unordered_multiset&) = default;
69b3331e
PC
742
743 unordered_multiset&
15ee1a77 744 operator=(unordered_multiset&&) = default;
69b3331e 745
988499f4
JM
746 unordered_multiset&
747 operator=(initializer_list<value_type> __l)
748 {
15ee1a77 749 this->_M_base() = __l;
0462b6aa 750 this->_M_invalidate_all();
988499f4
JM
751 return *this;
752 }
753
e63637ea 754 void
ff74fd13 755 swap(unordered_multiset& __x)
c5d9ec56 756 noexcept( noexcept(declval<_Base&>().swap(__x)) )
e63637ea 757 {
15ee1a77 758 _Safe::_M_swap(__x);
ced3cb9f 759 _Base::swap(__x);
e63637ea 760 }
69b3331e 761
ced3cb9f 762 void
d3677132 763 clear() noexcept
69b3331e
PC
764 {
765 _Base::clear();
766 this->_M_invalidate_all();
767 }
768
ced3cb9f 769 iterator
d3677132 770 begin() noexcept
ced3cb9f
PC
771 { return iterator(_Base::begin(), this); }
772
773 const_iterator
d3677132 774 begin() const noexcept
ced3cb9f
PC
775 { return const_iterator(_Base::begin(), this); }
776
777 iterator
d3677132 778 end() noexcept
ced3cb9f
PC
779 { return iterator(_Base::end(), this); }
780
781 const_iterator
d3677132 782 end() const noexcept
ced3cb9f
PC
783 { return const_iterator(_Base::end(), this); }
784
785 const_iterator
d3677132 786 cbegin() const noexcept
ced3cb9f
PC
787 { return const_iterator(_Base::begin(), this); }
788
789 const_iterator
d3677132 790 cend() const noexcept
ced3cb9f
PC
791 { return const_iterator(_Base::end(), this); }
792
793 // local versions
77e0bf4e
FD
794 local_iterator
795 begin(size_type __b)
7181e991
FD
796 {
797 __glibcxx_check_bucket_index(__b);
2e5189c8 798 return local_iterator(_Base::begin(__b), this);
7181e991 799 }
77e0bf4e
FD
800
801 local_iterator
802 end(size_type __b)
7181e991
FD
803 {
804 __glibcxx_check_bucket_index(__b);
2e5189c8 805 return local_iterator(_Base::end(__b), this);
7181e991 806 }
77e0bf4e
FD
807
808 const_local_iterator
809 begin(size_type __b) const
7181e991
FD
810 {
811 __glibcxx_check_bucket_index(__b);
2e5189c8 812 return const_local_iterator(_Base::begin(__b), this);
7181e991 813 }
77e0bf4e
FD
814
815 const_local_iterator
816 end(size_type __b) const
7181e991
FD
817 {
818 __glibcxx_check_bucket_index(__b);
2e5189c8 819 return const_local_iterator(_Base::end(__b), this);
7181e991 820 }
77e0bf4e
FD
821
822 const_local_iterator
823 cbegin(size_type __b) const
7181e991
FD
824 {
825 __glibcxx_check_bucket_index(__b);
2e5189c8 826 return const_local_iterator(_Base::cbegin(__b), this);
7181e991 827 }
77e0bf4e
FD
828
829 const_local_iterator
830 cend(size_type __b) const
7181e991
FD
831 {
832 __glibcxx_check_bucket_index(__b);
2e5189c8 833 return const_local_iterator(_Base::cend(__b), this);
7181e991
FD
834 }
835
836 size_type
837 bucket_size(size_type __b) const
838 {
839 __glibcxx_check_bucket_index(__b);
840 return _Base::bucket_size(__b);
841 }
14cbb5d8
FD
842
843 float
844 max_load_factor() const noexcept
845 { return _Base::max_load_factor(); }
846
847 void
848 max_load_factor(float __f)
849 {
850 __glibcxx_check_max_load_factor(__f);
851 _Base::max_load_factor(__f);
852 }
ced3cb9f 853
9b81593b
FD
854 template<typename... _Args>
855 iterator
856 emplace(_Args&&... __args)
857 {
858 size_type __bucket_count = this->bucket_count();
859 _Base_iterator __it
860 = _Base::emplace(std::forward<_Args>(__args)...);
861 _M_check_rehashed(__bucket_count);
862 return iterator(__it, this);
863 }
864
865 template<typename... _Args>
866 iterator
867 emplace_hint(const_iterator __hint, _Args&&... __args)
868 {
869 __glibcxx_check_insert(__hint);
870 size_type __bucket_count = this->bucket_count();
871 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
872 std::forward<_Args>(__args)...);
873 _M_check_rehashed(__bucket_count);
874 return iterator(__it, this);
875 }
876
ced3cb9f
PC
877 iterator
878 insert(const value_type& __obj)
77e0bf4e
FD
879 {
880 size_type __bucket_count = this->bucket_count();
881 _Base_iterator __it = _Base::insert(__obj);
882 _M_check_rehashed(__bucket_count);
883 return iterator(__it, this);
884 }
ced3cb9f
PC
885
886 iterator
d66411ba
FD
887 insert(const_iterator __hint, const value_type& __obj)
888 {
889 __glibcxx_check_insert(__hint);
77e0bf4e 890 size_type __bucket_count = this->bucket_count();
15ee1a77 891 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
77e0bf4e
FD
892 _M_check_rehashed(__bucket_count);
893 return iterator(__it, this);
d66411ba 894 }
ced3cb9f 895
fb7342fd
PC
896 iterator
897 insert(value_type&& __obj)
77e0bf4e
FD
898 {
899 size_type __bucket_count = this->bucket_count();
15ee1a77 900 _Base_iterator __it = _Base::insert(std::move(__obj));
77e0bf4e
FD
901 _M_check_rehashed(__bucket_count);
902 return iterator(__it, this);
903 }
fb7342fd
PC
904
905 iterator
d66411ba
FD
906 insert(const_iterator __hint, value_type&& __obj)
907 {
908 __glibcxx_check_insert(__hint);
77e0bf4e 909 size_type __bucket_count = this->bucket_count();
15ee1a77 910 _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj));
77e0bf4e
FD
911 _M_check_rehashed(__bucket_count);
912 return iterator(__it, this);
d66411ba 913 }
fb7342fd 914
ced3cb9f
PC
915 void
916 insert(std::initializer_list<value_type> __l)
77e0bf4e
FD
917 {
918 size_type __bucket_count = this->bucket_count();
919 _Base::insert(__l);
920 _M_check_rehashed(__bucket_count);
921 }
ced3cb9f
PC
922
923 template<typename _InputIterator>
77e0bf4e
FD
924 void
925 insert(_InputIterator __first, _InputIterator __last)
926 {
24167c42
FD
927 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
928 __glibcxx_check_valid_range2(__first, __last, __dist);
77e0bf4e 929 size_type __bucket_count = this->bucket_count();
24167c42
FD
930
931 if (__dist.second >= __gnu_debug::__dp_sign)
932 _Base::insert(__gnu_debug::__unsafe(__first),
933 __gnu_debug::__unsafe(__last));
934 else
935 _Base::insert(__first, __last);
936
77e0bf4e 937 _M_check_rehashed(__bucket_count);
ced3cb9f
PC
938 }
939
2dbe56bd
JW
940#if __cplusplus > 201402L
941 using node_type = typename _Base::node_type;
942
943 node_type
944 extract(const_iterator __position)
945 {
946 __glibcxx_check_erase(__position);
947 _Base_const_iterator __victim = __position.base();
948 this->_M_invalidate_if(
949 [__victim](_Base_const_iterator __it) { return __it == __victim; }
950 );
951 this->_M_invalidate_local_if(
952 [__victim](_Base_const_local_iterator __it) {
953 return __it._M_curr() == __victim._M_cur;
954 });
955 return _Base::extract(__position.base());
956 }
957
958 node_type
959 extract(const key_type& __key)
960 {
961 const auto __position = find(__key);
962 if (__position != end())
963 return extract(__position);
964 return {};
965 }
966
967 iterator
968 insert(node_type&& __nh)
969 { return iterator(_Base::insert(std::move(__nh)), this); }
970
971 iterator
972 insert(const_iterator __hint, node_type&& __nh)
973 {
974 __glibcxx_check_insert(__hint);
975 return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
976 }
977
978 using _Base::merge;
979#endif // C++17
980
ced3cb9f
PC
981 iterator
982 find(const key_type& __key)
983 { return iterator(_Base::find(__key), this); }
984
985 const_iterator
986 find(const key_type& __key) const
987 { return const_iterator(_Base::find(__key), this); }
988
989 std::pair<iterator, iterator>
990 equal_range(const key_type& __key)
991 {
15ee1a77
FD
992 std::pair<_Base_iterator, _Base_iterator> __res
993 = _Base::equal_range(__key);
ced3cb9f
PC
994 return std::make_pair(iterator(__res.first, this),
995 iterator(__res.second, this));
996 }
997
998 std::pair<const_iterator, const_iterator>
999 equal_range(const key_type& __key) const
1000 {
afe96d41
FD
1001 std::pair<_Base_const_iterator, _Base_const_iterator>
1002 __res = _Base::equal_range(__key);
ced3cb9f
PC
1003 return std::make_pair(const_iterator(__res.first, this),
1004 const_iterator(__res.second, this));
1005 }
1006
1007 size_type
1008 erase(const key_type& __key)
1009 {
1010 size_type __ret(0);
d3b8263e
FD
1011 std::pair<_Base_iterator, _Base_iterator> __pair =
1012 _Base::equal_range(__key);
1013 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
ced3cb9f 1014 {
77e0bf4e
FD
1015 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
1016 { return __it == __victim; });
77e0bf4e 1017 this->_M_invalidate_local_if(
5b3be7cf 1018 [__victim](_Base_const_local_iterator __it)
92e16228 1019 { return __it._M_curr() == __victim._M_cur; });
d3b8263e
FD
1020 _Base::erase(__victim++);
1021 ++__ret;
ced3cb9f
PC
1022 }
1023 return __ret;
1024 }
1025
d723ced2 1026 iterator
ced3cb9f
PC
1027 erase(const_iterator __it)
1028 {
1029 __glibcxx_check_erase(__it);
77e0bf4e
FD
1030 _Base_const_iterator __victim = __it.base();
1031 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
1032 { return __it == __victim; });
77e0bf4e 1033 this->_M_invalidate_local_if(
5b3be7cf 1034 [__victim](_Base_const_local_iterator __it)
92e16228 1035 { return __it._M_curr() == __victim._M_cur; });
d723ced2 1036 return iterator(_Base::erase(__it.base()), this);
ced3cb9f
PC
1037 }
1038
6dc88283
PC
1039 iterator
1040 erase(iterator __it)
1041 { return erase(const_iterator(__it)); }
1042
d723ced2 1043 iterator
ced3cb9f
PC
1044 erase(const_iterator __first, const_iterator __last)
1045 {
1046 __glibcxx_check_erase_range(__first, __last);
afe96d41
FD
1047 for (_Base_const_iterator __tmp = __first.base();
1048 __tmp != __last.base(); ++__tmp)
1049 {
1050 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
1051 _M_message(__gnu_debug::__msg_valid_range)
1052 ._M_iterator(__first, "first")
1053 ._M_iterator(__last, "last"));
77e0bf4e
FD
1054 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
1055 { return __it == __tmp; });
77e0bf4e 1056 this->_M_invalidate_local_if(
5b3be7cf 1057 [__tmp](_Base_const_local_iterator __it)
92e16228 1058 { return __it._M_curr() == __tmp._M_cur; });
afe96d41 1059 }
d723ced2
PC
1060 return iterator(_Base::erase(__first.base(),
1061 __last.base()), this);
ced3cb9f
PC
1062 }
1063
1064 _Base&
15ee1a77 1065 _M_base() noexcept { return *this; }
ced3cb9f
PC
1066
1067 const _Base&
15ee1a77 1068 _M_base() const noexcept { return *this; }
ced3cb9f 1069
69b3331e 1070 private:
77e0bf4e
FD
1071 void
1072 _M_check_rehashed(size_type __prev_count)
1073 {
1074 if (__prev_count != this->bucket_count())
15ee1a77 1075 this->_M_invalidate_locals();
69b3331e 1076 }
e63637ea
BK
1077 };
1078
957f5fea
VV
1079#if __cpp_deduction_guides >= 201606
1080
1081 template<typename _InputIterator,
1082 typename _Hash =
1083 hash<typename iterator_traits<_InputIterator>::value_type>,
1084 typename _Pred =
1085 equal_to<typename iterator_traits<_InputIterator>::value_type>,
1086 typename _Allocator =
1087 allocator<typename iterator_traits<_InputIterator>::value_type>,
1088 typename = _RequireInputIter<_InputIterator>,
1089 typename = _RequireAllocator<_Allocator>>
1090 unordered_multiset(_InputIterator, _InputIterator,
1091 unordered_multiset<int>::size_type = {},
1092 _Hash = _Hash(), _Pred = _Pred(),
1093 _Allocator = _Allocator())
1094 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
1095 _Hash, _Pred, _Allocator>;
1096
1097 template<typename _Tp, typename _Hash = hash<_Tp>,
1098 typename _Pred = equal_to<_Tp>,
1099 typename _Allocator = allocator<_Tp>,
1100 typename = _RequireAllocator<_Allocator>>
1101 unordered_multiset(initializer_list<_Tp>,
1102 unordered_multiset<int>::size_type = {},
1103 _Hash = _Hash(), _Pred = _Pred(),
1104 _Allocator = _Allocator())
1105 -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>;
1106
1107 template<typename _InputIterator, typename _Allocator,
1108 typename = _RequireInputIter<_InputIterator>,
1109 typename = _RequireAllocator<_Allocator>>
1110 unordered_multiset(_InputIterator, _InputIterator,
1111 unordered_multiset<int>::size_type, _Allocator)
1112 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
1113 hash<typename
1114 iterator_traits<_InputIterator>::value_type>,
1115 equal_to<typename
1116 iterator_traits<_InputIterator>::value_type>,
1117 _Allocator>;
1118
1119 template<typename _InputIterator, typename _Hash, typename _Allocator,
1120 typename = _RequireInputIter<_InputIterator>,
1121 typename = _RequireAllocator<_Allocator>>
1122 unordered_multiset(_InputIterator, _InputIterator,
1123 unordered_multiset<int>::size_type,
1124 _Hash, _Allocator)
1125 -> unordered_multiset<typename
1126 iterator_traits<_InputIterator>::value_type,
1127 _Hash,
1128 equal_to<
1129 typename
1130 iterator_traits<_InputIterator>::value_type>,
1131 _Allocator>;
1132
1133 template<typename _Tp, typename _Allocator,
1134 typename = _RequireAllocator<_Allocator>>
1135 unordered_multiset(initializer_list<_Tp>,
1136 unordered_multiset<int>::size_type, _Allocator)
1137 -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
1138
1139 template<typename _Tp, typename _Hash, typename _Allocator,
1140 typename = _RequireAllocator<_Allocator>>
1141 unordered_multiset(initializer_list<_Tp>,
1142 unordered_multiset<int>::size_type, _Hash, _Allocator)
1143 -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>;
1144
1145#endif
1146
e63637ea 1147 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
69b3331e
PC
1148 inline void
1149 swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1150 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
c5d9ec56 1151 noexcept(noexcept(__x.swap(__y)))
69b3331e 1152 { __x.swap(__y); }
e63637ea 1153
5dc22714
PC
1154 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1155 inline bool
1156 operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1157 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
637fd8b3 1158 { return __x._M_base() == __y._M_base(); }
5dc22714
PC
1159
1160 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1161 inline bool
1162 operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1163 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1164 { return !(__x == __y); }
1165
e63637ea
BK
1166} // namespace __debug
1167} // namespace std
1168
734f5023 1169#endif // C++11
c878d6ba 1170
e63637ea 1171#endif