Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6554 serge 1
// Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
2
 
3
// Copyright (C) 2003-2015 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
// .
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
#if __cplusplus < 201103L
33
# include 
34
#else
35
# include 
36
 
37
#include 
38
#include 
39
#include 
40
#include 
41
 
42
namespace std _GLIBCXX_VISIBILITY(default)
43
{
44
namespace __debug
45
{
46
  /// Class std::unordered_map with safety/checking/debug instrumentation.
47
  template
48
	   typename _Hash = std::hash<_Key>,
49
	   typename _Pred = std::equal_to<_Key>,
50
	   typename _Alloc = std::allocator > >
51
    class unordered_map
52
    : public __gnu_debug::_Safe_container<
53
	unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
54
	__gnu_debug::_Safe_unordered_container>,
55
      public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
56
    {
57
      typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
58
					    _Pred, _Alloc>		_Base;
59
      typedef __gnu_debug::_Safe_container
60
		   _Alloc, __gnu_debug::_Safe_unordered_container>	_Safe;
61
      typedef typename _Base::const_iterator	_Base_const_iterator;
62
      typedef typename _Base::iterator		_Base_iterator;
63
      typedef typename _Base::const_local_iterator
64
						_Base_const_local_iterator;
65
      typedef typename _Base::local_iterator	_Base_local_iterator;
66
 
67
    public:
68
      typedef typename _Base::size_type			size_type;
69
      typedef typename _Base::hasher			hasher;
70
      typedef typename _Base::key_equal			key_equal;
71
      typedef typename _Base::allocator_type		allocator_type;
72
 
73
      typedef typename _Base::key_type			key_type;
74
      typedef typename _Base::value_type		value_type;
75
 
76
      typedef __gnu_debug::_Safe_iterator<
77
	_Base_iterator, unordered_map>			iterator;
78
      typedef __gnu_debug::_Safe_iterator<
79
	_Base_const_iterator, unordered_map>		const_iterator;
80
      typedef __gnu_debug::_Safe_local_iterator<
81
	_Base_local_iterator, unordered_map>		local_iterator;
82
      typedef __gnu_debug::_Safe_local_iterator<
83
	_Base_const_local_iterator, unordered_map>	const_local_iterator;
84
 
85
      unordered_map() = default;
86
 
87
      explicit
88
      unordered_map(size_type __n,
89
		    const hasher& __hf = hasher(),
90
		    const key_equal& __eql = key_equal(),
91
		    const allocator_type& __a = allocator_type())
92
      : _Base(__n, __hf, __eql, __a) { }
93
 
94
      template
95
	unordered_map(_InputIterator __first, _InputIterator __last,
96
		      size_type __n = 0,
97
		      const hasher& __hf = hasher(),
98
		      const key_equal& __eql = key_equal(),
99
		      const allocator_type& __a = allocator_type())
100
	: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
101
								     __last)),
102
		__gnu_debug::__base(__last), __n,
103
		__hf, __eql, __a) { }
104
 
105
      unordered_map(const unordered_map&) = default;
106
 
107
      unordered_map(const _Base& __x)
108
      : _Base(__x) { }
109
 
110
      unordered_map(unordered_map&&) = default;
111
 
112
      explicit
113
      unordered_map(const allocator_type& __a)
114
      : _Base(__a) { }
115
 
116
      unordered_map(const unordered_map& __umap,
117
		    const allocator_type& __a)
118
      : _Base(__umap, __a) { }
119
 
120
      unordered_map(unordered_map&& __umap,
121
		    const allocator_type& __a)
122
      : _Safe(std::move(__umap._M_safe()), __a),
123
	_Base(std::move(__umap._M_base()), __a) { }
124
 
125
      unordered_map(initializer_list __l,
126
		    size_type __n = 0,
127
		    const hasher& __hf = hasher(),
128
		    const key_equal& __eql = key_equal(),
129
		    const allocator_type& __a = allocator_type())
130
      : _Base(__l, __n, __hf, __eql, __a) { }
131
 
132
      unordered_map(size_type __n, const allocator_type& __a)
133
      : unordered_map(__n, hasher(), key_equal(), __a)
134
      { }
135
 
136
      unordered_map(size_type __n,
137
		    const hasher& __hf,
138
		    const allocator_type& __a)
139
      : unordered_map(__n, __hf, key_equal(), __a)
140
      { }
141
 
142
      template
143
	unordered_map(_InputIterator __first, _InputIterator __last,
144
		      size_type __n,
145
		      const allocator_type& __a)
146
	  : unordered_map(__first, __last, __n, hasher(), key_equal(), __a)
147
	{ }
148
 
149
      template
150
	unordered_map(_InputIterator __first, _InputIterator __last,
151
		      size_type __n,
152
		      const hasher& __hf,
153
		      const allocator_type& __a)
154
	  : unordered_map(__first, __last, __n, __hf, key_equal(), __a)
155
	{ }
156
 
157
      unordered_map(initializer_list __l,
158
		    size_type __n,
159
		    const allocator_type& __a)
160
	: unordered_map(__l, __n, hasher(), key_equal(), __a)
161
      { }
162
 
163
      unordered_map(initializer_list __l,
164
		    size_type __n,
165
		    const hasher& __hf,
166
		    const allocator_type& __a)
167
	: unordered_map(__l, __n, __hf, key_equal(), __a)
168
      { }
169
 
170
      ~unordered_map() = default;
171
 
172
      unordered_map&
173
      operator=(const unordered_map&) = default;
174
 
175
      unordered_map&
176
      operator=(unordered_map&&) = default;
177
 
178
      unordered_map&
179
      operator=(initializer_list __l)
180
      {
181
	_M_base() = __l;
182
	this->_M_invalidate_all();
183
	return *this;
184
      }
185
 
186
      void
187
      swap(unordered_map& __x)
188
	noexcept( noexcept(declval<_Base>().swap(__x)) )
189
      {
190
	_Safe::_M_swap(__x);
191
	_Base::swap(__x);
192
      }
193
 
194
      void
195
      clear() noexcept
196
      {
197
	_Base::clear();
198
	this->_M_invalidate_all();
199
      }
200
 
201
      iterator
202
      begin() noexcept
203
      { return iterator(_Base::begin(), this); }
204
 
205
      const_iterator
206
      begin() const noexcept
207
      { return const_iterator(_Base::begin(), this); }
208
 
209
      iterator
210
      end() noexcept
211
      { return iterator(_Base::end(), this); }
212
 
213
      const_iterator
214
      end() const noexcept
215
      { return const_iterator(_Base::end(), this); }
216
 
217
      const_iterator
218
      cbegin() const noexcept
219
      { return const_iterator(_Base::begin(), this); }
220
 
221
      const_iterator
222
      cend() const noexcept
223
      { return const_iterator(_Base::end(), this); }
224
 
225
      // local versions
226
      local_iterator
227
      begin(size_type __b)
228
      {
229
	__glibcxx_check_bucket_index(__b);
230
	return local_iterator(_Base::begin(__b), this);
231
      }
232
 
233
      local_iterator
234
      end(size_type __b)
235
      {
236
	__glibcxx_check_bucket_index(__b);
237
	return local_iterator(_Base::end(__b), this);
238
      }
239
 
240
      const_local_iterator
241
      begin(size_type __b) const
242
      {
243
	__glibcxx_check_bucket_index(__b);
244
	return const_local_iterator(_Base::begin(__b), this);
245
      }
246
 
247
      const_local_iterator
248
      end(size_type __b) const
249
      {
250
	__glibcxx_check_bucket_index(__b);
251
	return const_local_iterator(_Base::end(__b), this);
252
      }
253
 
254
      const_local_iterator
255
      cbegin(size_type __b) const
256
      {
257
	__glibcxx_check_bucket_index(__b);
258
	return const_local_iterator(_Base::cbegin(__b), this);
259
      }
260
 
261
      const_local_iterator
262
      cend(size_type __b) const
263
      {
264
	__glibcxx_check_bucket_index(__b);
265
	return const_local_iterator(_Base::cend(__b), this);
266
      }
267
 
268
      size_type
269
      bucket_size(size_type __b) const
270
      {
271
	__glibcxx_check_bucket_index(__b);
272
	return _Base::bucket_size(__b);
273
      }
274
 
275
      float
276
      max_load_factor() const noexcept
277
      { return _Base::max_load_factor(); }
278
 
279
      void
280
      max_load_factor(float __f)
281
      {
282
	__glibcxx_check_max_load_factor(__f);
283
	_Base::max_load_factor(__f);
284
      }
285
 
286
      template
287
	std::pair
288
	emplace(_Args&&... __args)
289
	{
290
	  size_type __bucket_count = this->bucket_count();
291
	  std::pair<_Base_iterator, bool> __res
292
	    = _Base::emplace(std::forward<_Args>(__args)...);
293
	  _M_check_rehashed(__bucket_count);
294
	  return std::make_pair(iterator(__res.first, this), __res.second);
295
	}
296
 
297
      template
298
	iterator
299
	emplace_hint(const_iterator __hint, _Args&&... __args)
300
	{
301
	  __glibcxx_check_insert(__hint);
302
	  size_type __bucket_count = this->bucket_count();
303
	  _Base_iterator __it = _Base::emplace_hint(__hint.base(),
304
					std::forward<_Args>(__args)...);
305
	  _M_check_rehashed(__bucket_count);
306
	  return iterator(__it, this);
307
	}
308
 
309
      std::pair
310
      insert(const value_type& __obj)
311
      {
312
	size_type __bucket_count = this->bucket_count();
313
	std::pair<_Base_iterator, bool> __res = _Base::insert(__obj);
314
	_M_check_rehashed(__bucket_count);
315
	return std::make_pair(iterator(__res.first, this), __res.second);
316
      }
317
 
318
      iterator
319
      insert(const_iterator __hint, const value_type& __obj)
320
      {
321
	__glibcxx_check_insert(__hint);
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);
326
      }
327
 
328
      template
329
	       std::enable_if
330
						    _Pair&&>::value>::type>
331
	std::pair
332
	insert(_Pair&& __obj)
333
	{
334
	  size_type __bucket_count = this->bucket_count();
335
	  std::pair<_Base_iterator, bool> __res =
336
	    _Base::insert(std::forward<_Pair>(__obj));
337
	  _M_check_rehashed(__bucket_count);
338
	  return std::make_pair(iterator(__res.first, this), __res.second);
339
	}
340
 
341
      template
342
	       std::enable_if
343
						    _Pair&&>::value>::type>
344
	iterator
345
	insert(const_iterator __hint, _Pair&& __obj)
346
	{
347
	  __glibcxx_check_insert(__hint);
348
	  size_type __bucket_count = this->bucket_count();
349
	  _Base_iterator __it =
350
	    _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
351
	  _M_check_rehashed(__bucket_count);
352
	  return iterator(__it, this);
353
	}
354
 
355
      void
356
      insert(std::initializer_list __l)
357
      {
358
	size_type __bucket_count = this->bucket_count();
359
	_Base::insert(__l);
360
	_M_check_rehashed(__bucket_count);
361
      }
362
 
363
      template
364
	void
365
	insert(_InputIterator __first, _InputIterator __last)
366
	{
367
	  __glibcxx_check_valid_range(__first, __last);
368
	  size_type __bucket_count = this->bucket_count();
369
	  _Base::insert(__gnu_debug::__base(__first),
370
			  __gnu_debug::__base(__last));
371
	  _M_check_rehashed(__bucket_count);
372
	}
373
 
374
      iterator
375
      find(const key_type& __key)
376
      { return iterator(_Base::find(__key), this); }
377
 
378
      const_iterator
379
      find(const key_type& __key) const
380
      { return const_iterator(_Base::find(__key), this); }
381
 
382
      std::pair
383
      equal_range(const key_type& __key)
384
      {
385
	std::pair<_Base_iterator, _Base_iterator> __res =
386
	  _Base::equal_range(__key);
387
	return std::make_pair(iterator(__res.first, this),
388
			      iterator(__res.second, this));
389
      }
390
 
391
      std::pair
392
      equal_range(const key_type& __key) const
393
      {
394
	std::pair<_Base_const_iterator, _Base_const_iterator> __res =
395
	  _Base::equal_range(__key);
396
	return std::make_pair(const_iterator(__res.first, this),
397
			      const_iterator(__res.second, this));
398
      }
399
 
400
      size_type
401
      erase(const key_type& __key)
402
      {
403
	size_type __ret(0);
404
	_Base_iterator __victim(_Base::find(__key));
405
	if (__victim != _Base::end())
406
	  {
407
	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
408
			    { return __it == __victim; });
409
	    this->_M_invalidate_local_if(
410
			    [__victim](_Base_const_local_iterator __it)
411
			    { return __it._M_curr() == __victim._M_cur; });
412
	    size_type __bucket_count = this->bucket_count();
413
	    _Base::erase(__victim);
414
	    _M_check_rehashed(__bucket_count);
415
	    __ret = 1;
416
	  }
417
	return __ret;
418
      }
419
 
420
      iterator
421
      erase(const_iterator __it)
422
      {
423
	__glibcxx_check_erase(__it);
424
	_Base_const_iterator __victim = __it.base();
425
	this->_M_invalidate_if([__victim](_Base_const_iterator __it)
426
			{ return __it == __victim; });
427
	this->_M_invalidate_local_if(
428
			[__victim](_Base_const_local_iterator __it)
429
			{ return __it._M_curr() == __victim._M_cur; });
430
	size_type __bucket_count = this->bucket_count();
431
	_Base_iterator __next = _Base::erase(__it.base());
432
	_M_check_rehashed(__bucket_count);
433
	return iterator(__next, this);
434
      }
435
 
436
      iterator
437
      erase(iterator __it)
438
      { return erase(const_iterator(__it)); }
439
 
440
      iterator
441
      erase(const_iterator __first, const_iterator __last)
442
      {
443
	__glibcxx_check_erase_range(__first, __last);
444
	for (_Base_const_iterator __tmp = __first.base();
445
	     __tmp != __last.base(); ++__tmp)
446
	  {
447
	    _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
448
				  _M_message(__gnu_debug::__msg_valid_range)
449
				  ._M_iterator(__first, "first")
450
				  ._M_iterator(__last, "last"));
451
	    this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
452
			    { return __it == __tmp; });
453
	    this->_M_invalidate_local_if(
454
			    [__tmp](_Base_const_local_iterator __it)
455
			    { return __it._M_curr() == __tmp._M_cur; });
456
	  }
457
	size_type __bucket_count = this->bucket_count();
458
	_Base_iterator __next = _Base::erase(__first.base(), __last.base());
459
	_M_check_rehashed(__bucket_count);
460
	return iterator(__next, this);
461
      }
462
 
463
      _Base&
464
      _M_base() noexcept	{ return *this; }
465
 
466
      const _Base&
467
      _M_base() const noexcept	{ return *this; }
468
 
469
    private:
470
      void
471
      _M_check_rehashed(size_type __prev_count)
472
      {
473
	if (__prev_count != this->bucket_count())
474
	  this->_M_invalidate_locals();
475
      }
476
    };
477
 
478
  template
479
	   typename _Pred, typename _Alloc>
480
    inline void
481
    swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
482
	 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
483
    { __x.swap(__y); }
484
 
485
  template
486
	   typename _Pred, typename _Alloc>
487
    inline bool
488
    operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
489
	       const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
490
    { return __x._M_base() == __y._M_base(); }
491
 
492
  template
493
	   typename _Pred, typename _Alloc>
494
    inline bool
495
    operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
496
	       const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
497
    { return !(__x == __y); }
498
 
499
 
500
  /// Class std::unordered_multimap with safety/checking/debug instrumentation.
501
  template
502
	   typename _Hash = std::hash<_Key>,
503
	   typename _Pred = std::equal_to<_Key>,
504
	   typename _Alloc = std::allocator > >
505
    class unordered_multimap
506
      : public __gnu_debug::_Safe_container<
507
	unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
508
	__gnu_debug::_Safe_unordered_container>,
509
	public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
510
    {
511
      typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
512
						 _Pred, _Alloc>		_Base;
513
      typedef __gnu_debug::_Safe_container
514
	_Alloc, __gnu_debug::_Safe_unordered_container>			_Safe;
515
      typedef typename _Base::const_iterator	   _Base_const_iterator;
516
      typedef typename _Base::iterator		   _Base_iterator;
517
      typedef typename _Base::const_local_iterator _Base_const_local_iterator;
518
      typedef typename _Base::local_iterator	   _Base_local_iterator;
519
 
520
    public:
521
      typedef typename _Base::size_type			size_type;
522
      typedef typename _Base::hasher			hasher;
523
      typedef typename _Base::key_equal			key_equal;
524
      typedef typename _Base::allocator_type		allocator_type;
525
 
526
      typedef typename _Base::key_type			key_type;
527
      typedef typename _Base::value_type		value_type;
528
 
529
      typedef __gnu_debug::_Safe_iterator<
530
	_Base_iterator, unordered_multimap>		iterator;
531
      typedef __gnu_debug::_Safe_iterator<
532
	_Base_const_iterator, unordered_multimap>	const_iterator;
533
      typedef __gnu_debug::_Safe_local_iterator<
534
	_Base_local_iterator, unordered_multimap>	local_iterator;
535
      typedef __gnu_debug::_Safe_local_iterator<
536
	_Base_const_local_iterator, unordered_multimap> const_local_iterator;
537
 
538
      unordered_multimap() = default;
539
 
540
      explicit
541
      unordered_multimap(size_type __n,
542
			 const hasher& __hf = hasher(),
543
			 const key_equal& __eql = key_equal(),
544
			 const allocator_type& __a = allocator_type())
545
      : _Base(__n, __hf, __eql, __a) { }
546
 
547
      template
548
	unordered_multimap(_InputIterator __first, _InputIterator __last,
549
			   size_type __n = 0,
550
			   const hasher& __hf = hasher(),
551
			   const key_equal& __eql = key_equal(),
552
			   const allocator_type& __a = allocator_type())
553
	: _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
554
								     __last)),
555
		__gnu_debug::__base(__last), __n,
556
		__hf, __eql, __a) { }
557
 
558
      unordered_multimap(const unordered_multimap&) = default;
559
 
560
      unordered_multimap(const _Base& __x)
561
      : _Base(__x) { }
562
 
563
      unordered_multimap(unordered_multimap&&) = default;
564
 
565
      explicit
566
      unordered_multimap(const allocator_type& __a)
567
      : _Base(__a) { }
568
 
569
      unordered_multimap(const unordered_multimap& __umap,
570
			 const allocator_type& __a)
571
      : _Base(__umap, __a) { }
572
 
573
      unordered_multimap(unordered_multimap&& __umap,
574
			 const allocator_type& __a)
575
      : _Safe(std::move(__umap._M_safe()), __a),
576
	_Base(std::move(__umap._M_base()), __a) { }
577
 
578
      unordered_multimap(initializer_list __l,
579
			 size_type __n = 0,
580
			 const hasher& __hf = hasher(),
581
			 const key_equal& __eql = key_equal(),
582
			 const allocator_type& __a = allocator_type())
583
      : _Base(__l, __n, __hf, __eql, __a) { }
584
 
585
      unordered_multimap(size_type __n, const allocator_type& __a)
586
      : unordered_multimap(__n, hasher(), key_equal(), __a)
587
      { }
588
 
589
      unordered_multimap(size_type __n, const hasher& __hf,
590
			 const allocator_type& __a)
591
      : unordered_multimap(__n, __hf, key_equal(), __a)
592
      { }
593
 
594
      template
595
	unordered_multimap(_InputIterator __first, _InputIterator __last,
596
			   size_type __n,
597
			   const allocator_type& __a)
598
	  : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a)
599
	{ }
600
 
601
      template
602
	unordered_multimap(_InputIterator __first, _InputIterator __last,
603
			   size_type __n, const hasher& __hf,
604
			   const allocator_type& __a)
605
	  : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a)
606
	{ }
607
 
608
      unordered_multimap(initializer_list __l,
609
			 size_type __n,
610
			 const allocator_type& __a)
611
	: unordered_multimap(__l, __n, hasher(), key_equal(), __a)
612
      { }
613
 
614
      unordered_multimap(initializer_list __l,
615
			 size_type __n, const hasher& __hf,
616
			 const allocator_type& __a)
617
	: unordered_multimap(__l, __n, __hf, key_equal(), __a)
618
      { }
619
 
620
      ~unordered_multimap() = default;
621
 
622
      unordered_multimap&
623
      operator=(const unordered_multimap&) = default;
624
 
625
      unordered_multimap&
626
      operator=(unordered_multimap&&) = default;
627
 
628
      unordered_multimap&
629
      operator=(initializer_list __l)
630
      {
631
	this->_M_base() = __l;
632
	this->_M_invalidate_all();
633
	return *this;
634
      }
635
 
636
      void
637
      swap(unordered_multimap& __x)
638
	noexcept( noexcept(declval<_Base>().swap(__x)) )
639
      {
640
	_Safe::_M_swap(__x);
641
	_Base::swap(__x);
642
      }
643
 
644
      void
645
      clear() noexcept
646
      {
647
	_Base::clear();
648
	this->_M_invalidate_all();
649
      }
650
 
651
      iterator
652
      begin() noexcept
653
      { return iterator(_Base::begin(), this); }
654
 
655
      const_iterator
656
      begin() const noexcept
657
      { return const_iterator(_Base::begin(), this); }
658
 
659
      iterator
660
      end() noexcept
661
      { return iterator(_Base::end(), this); }
662
 
663
      const_iterator
664
      end() const noexcept
665
      { return const_iterator(_Base::end(), this); }
666
 
667
      const_iterator
668
      cbegin() const noexcept
669
      { return const_iterator(_Base::begin(), this); }
670
 
671
      const_iterator
672
      cend() const noexcept
673
      { return const_iterator(_Base::end(), this); }
674
 
675
      // local versions
676
      local_iterator
677
      begin(size_type __b)
678
      {
679
	__glibcxx_check_bucket_index(__b);
680
	return local_iterator(_Base::begin(__b), this);
681
      }
682
 
683
      local_iterator
684
      end(size_type __b)
685
      {
686
	__glibcxx_check_bucket_index(__b);
687
	return local_iterator(_Base::end(__b), this);
688
      }
689
 
690
      const_local_iterator
691
      begin(size_type __b) const
692
      {
693
	__glibcxx_check_bucket_index(__b);
694
	return const_local_iterator(_Base::begin(__b), this);
695
      }
696
 
697
      const_local_iterator
698
      end(size_type __b) const
699
      {
700
	__glibcxx_check_bucket_index(__b);
701
	return const_local_iterator(_Base::end(__b), this);
702
      }
703
 
704
      const_local_iterator
705
      cbegin(size_type __b) const
706
      {
707
	__glibcxx_check_bucket_index(__b);
708
	return const_local_iterator(_Base::cbegin(__b), this);
709
      }
710
 
711
      const_local_iterator
712
      cend(size_type __b) const
713
      {
714
	__glibcxx_check_bucket_index(__b);
715
	return const_local_iterator(_Base::cend(__b), this);
716
      }
717
 
718
      size_type
719
      bucket_size(size_type __b) const
720
      {
721
	__glibcxx_check_bucket_index(__b);
722
	return _Base::bucket_size(__b);
723
      }
724
 
725
      float
726
      max_load_factor() const noexcept
727
      { return _Base::max_load_factor(); }
728
 
729
      void
730
      max_load_factor(float __f)
731
      {
732
	__glibcxx_check_max_load_factor(__f);
733
	_Base::max_load_factor(__f);
734
      }
735
 
736
      template
737
	iterator
738
	emplace(_Args&&... __args)
739
	{
740
	  size_type __bucket_count = this->bucket_count();
741
	  _Base_iterator __it
742
	    = _Base::emplace(std::forward<_Args>(__args)...);
743
	  _M_check_rehashed(__bucket_count);
744
	  return iterator(__it, this);
745
	}
746
 
747
      template
748
	iterator
749
	emplace_hint(const_iterator __hint, _Args&&... __args)
750
	{
751
	  __glibcxx_check_insert(__hint);
752
	  size_type __bucket_count = this->bucket_count();
753
	  _Base_iterator __it = _Base::emplace_hint(__hint.base(),
754
					std::forward<_Args>(__args)...);
755
	  _M_check_rehashed(__bucket_count);
756
	  return iterator(__it, this);
757
	}
758
 
759
      iterator
760
      insert(const value_type& __obj)
761
      {
762
	size_type __bucket_count = this->bucket_count();
763
	_Base_iterator __it = _Base::insert(__obj);
764
	_M_check_rehashed(__bucket_count);
765
	return iterator(__it, this);
766
      }
767
 
768
      iterator
769
      insert(const_iterator __hint, const value_type& __obj)
770
      {
771
	__glibcxx_check_insert(__hint);
772
	size_type __bucket_count = this->bucket_count();
773
	_Base_iterator __it = _Base::insert(__hint.base(), __obj);
774
	_M_check_rehashed(__bucket_count);
775
	return iterator(__it, this);
776
      }
777
 
778
      template
779
	       std::enable_if
780
						    _Pair&&>::value>::type>
781
	iterator
782
	insert(_Pair&& __obj)
783
	{
784
	  size_type __bucket_count = this->bucket_count();
785
	  _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj));
786
	  _M_check_rehashed(__bucket_count);
787
	  return iterator(__it, this);
788
	}
789
 
790
      template
791
	       std::enable_if
792
						    _Pair&&>::value>::type>
793
	iterator
794
	insert(const_iterator __hint, _Pair&& __obj)
795
	{
796
	  __glibcxx_check_insert(__hint);
797
	  size_type __bucket_count = this->bucket_count();
798
	  _Base_iterator __it =
799
	    _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
800
	  _M_check_rehashed(__bucket_count);
801
	  return iterator(__it, this);
802
	}
803
 
804
      void
805
      insert(std::initializer_list __l)
806
      { _Base::insert(__l); }
807
 
808
      template
809
	void
810
	insert(_InputIterator __first, _InputIterator __last)
811
	{
812
	  __glibcxx_check_valid_range(__first, __last);
813
	  size_type __bucket_count = this->bucket_count();
814
	  _Base::insert(__gnu_debug::__base(__first),
815
			__gnu_debug::__base(__last));
816
	  _M_check_rehashed(__bucket_count);
817
	}
818
 
819
      iterator
820
      find(const key_type& __key)
821
      { return iterator(_Base::find(__key), this); }
822
 
823
      const_iterator
824
      find(const key_type& __key) const
825
      { return const_iterator(_Base::find(__key), this); }
826
 
827
      std::pair
828
      equal_range(const key_type& __key)
829
      {
830
	std::pair<_Base_iterator, _Base_iterator> __res =
831
	  _Base::equal_range(__key);
832
	return std::make_pair(iterator(__res.first, this),
833
			      iterator(__res.second, this));
834
      }
835
 
836
      std::pair
837
      equal_range(const key_type& __key) const
838
      {
839
	std::pair<_Base_const_iterator, _Base_const_iterator> __res =
840
	  _Base::equal_range(__key);
841
	return std::make_pair(const_iterator(__res.first, this),
842
			      const_iterator(__res.second, this));
843
      }
844
 
845
      size_type
846
      erase(const key_type& __key)
847
      {
848
	size_type __ret(0);
849
	size_type __bucket_count = this->bucket_count();
850
	std::pair<_Base_iterator, _Base_iterator> __pair =
851
	  _Base::equal_range(__key);
852
	for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
853
	  {
854
	    this->_M_invalidate_if([__victim](_Base_const_iterator __it)
855
			    { return __it == __victim; });
856
	    this->_M_invalidate_local_if(
857
			    [__victim](_Base_const_local_iterator __it)
858
			    { return __it._M_curr() == __victim._M_cur; });
859
	    _Base::erase(__victim++);
860
	    ++__ret;
861
	  }
862
	_M_check_rehashed(__bucket_count);
863
	return __ret;
864
      }
865
 
866
      iterator
867
      erase(const_iterator __it)
868
      {
869
	__glibcxx_check_erase(__it);
870
	_Base_const_iterator __victim = __it.base();
871
	this->_M_invalidate_if([__victim](_Base_const_iterator __it)
872
			{ return __it == __victim; });
873
	this->_M_invalidate_local_if(
874
			[__victim](_Base_const_local_iterator __it)
875
			{ return __it._M_curr() == __victim._M_cur; });
876
	size_type __bucket_count = this->bucket_count();
877
	_Base_iterator __next = _Base::erase(__it.base());
878
	_M_check_rehashed(__bucket_count);
879
	return iterator(__next, this);
880
      }
881
 
882
      iterator
883
      erase(iterator __it)
884
      { return erase(const_iterator(__it)); }
885
 
886
      iterator
887
      erase(const_iterator __first, const_iterator __last)
888
      {
889
	__glibcxx_check_erase_range(__first, __last);
890
	for (_Base_const_iterator __tmp = __first.base();
891
	     __tmp != __last.base(); ++__tmp)
892
	  {
893
	    _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
894
				  _M_message(__gnu_debug::__msg_valid_range)
895
				  ._M_iterator(__first, "first")
896
				  ._M_iterator(__last, "last"));
897
	    this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
898
			    { return __it == __tmp; });
899
	    this->_M_invalidate_local_if(
900
			    [__tmp](_Base_const_local_iterator __it)
901
			    { return __it._M_curr() == __tmp._M_cur; });
902
	  }
903
	size_type __bucket_count = this->bucket_count();
904
	_Base_iterator __next = _Base::erase(__first.base(), __last.base());
905
	_M_check_rehashed(__bucket_count);
906
	return iterator(__next, this);
907
      }
908
 
909
      _Base&
910
      _M_base() noexcept { return *this; }
911
 
912
      const _Base&
913
      _M_base() const noexcept { return *this; }
914
 
915
    private:
916
      void
917
      _M_check_rehashed(size_type __prev_count)
918
      {
919
	if (__prev_count != this->bucket_count())
920
	  this->_M_invalidate_locals();
921
      }
922
    };
923
 
924
  template
925
	   typename _Pred, typename _Alloc>
926
    inline void
927
    swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
928
	 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
929
    { __x.swap(__y); }
930
 
931
  template
932
	   typename _Pred, typename _Alloc>
933
    inline bool
934
    operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
935
	       const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
936
    { return __x._M_base() == __y._M_base(); }
937
 
938
  template
939
	   typename _Pred, typename _Alloc>
940
    inline bool
941
    operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
942
	       const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
943
    { return !(__x == __y); }
944
 
945
} // namespace __debug
946
} // namespace std
947
 
948
#endif // C++11
949
 
950
#endif