libstdc++
debug/unordered_set
Go to the documentation of this file.
1 // Debugging unordered_set/unordered_multiset implementation -*- C++ -*-
2 
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11 
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20 
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
25 
26 /** @file debug/unordered_set
27  * This file is a GNU debug extension to the Standard C++ Library.
28  */
29 
30 #ifndef _GLIBCXX_DEBUG_UNORDERED_SET
31 #define _GLIBCXX_DEBUG_UNORDERED_SET 1
32 
33 #ifndef __GXX_EXPERIMENTAL_CXX0X__
34 # include <bits/c++0x_warning.h>
35 #else
36 # include <unordered_set>
37 
38 #include <debug/safe_sequence.h>
39 #include <debug/safe_iterator.h>
40 
41 namespace std _GLIBCXX_VISIBILITY(default)
42 {
43 namespace __debug
44 {
45  /// Class std::unordered_set with safety/checking/debug instrumentation.
46  template<typename _Value,
47  typename _Hash = std::hash<_Value>,
48  typename _Pred = std::equal_to<_Value>,
49  typename _Alloc = std::allocator<_Value> >
51  : public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>,
52  public __gnu_debug::_Safe_sequence<unordered_set<_Value, _Hash,
53  _Pred, _Alloc> >
54  {
55  typedef _GLIBCXX_STD_C::unordered_set<_Value, _Hash,
56  _Pred, _Alloc> _Base;
59  typedef typename _Base::iterator _Base_iterator;
61 
62  public:
63  typedef typename _Base::size_type size_type;
64  typedef typename _Base::hasher hasher;
65  typedef typename _Base::key_equal key_equal;
66  typedef typename _Base::allocator_type allocator_type;
67 
68  typedef typename _Base::key_type key_type;
69  typedef typename _Base::value_type value_type;
70 
75 
76  explicit
77  unordered_set(size_type __n = 10,
78  const hasher& __hf = hasher(),
79  const key_equal& __eql = key_equal(),
80  const allocator_type& __a = allocator_type())
81  : _Base(__n, __hf, __eql, __a) { }
82 
83  template<typename _InputIterator>
84  unordered_set(_InputIterator __first, _InputIterator __last,
85  size_type __n = 0,
86  const hasher& __hf = hasher(),
87  const key_equal& __eql = key_equal(),
88  const allocator_type& __a = allocator_type())
89  : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
90  __last)),
91  __gnu_debug::__base(__last), __n,
92  __hf, __eql, __a), _Safe_base() { }
93 
94  unordered_set(const unordered_set& __x)
95  : _Base(__x), _Safe_base() { }
96 
97  unordered_set(const _Base& __x)
98  : _Base(__x), _Safe_base() { }
99 
101  : _Base(std::move(__x)), _Safe_base() { }
102 
104  size_type __n = 0,
105  const hasher& __hf = hasher(),
106  const key_equal& __eql = key_equal(),
107  const allocator_type& __a = allocator_type())
108  : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { }
109 
111  operator=(const unordered_set& __x)
112  {
113  *static_cast<_Base*>(this) = __x;
114  this->_M_invalidate_all();
115  return *this;
116  }
117 
119  operator=(unordered_set&& __x)
120  {
121  // NB: DR 1204.
122  // NB: DR 675.
123  clear();
124  swap(__x);
125  return *this;
126  }
127 
129  operator=(initializer_list<value_type> __l)
130  {
131  this->clear();
132  this->insert(__l);
133  return *this;
134  }
135 
136  void
137  swap(unordered_set& __x)
138  {
139  _Base::swap(__x);
140  _Safe_base::_M_swap(__x);
141  }
142 
143  void
144  clear()
145  {
146  _Base::clear();
147  this->_M_invalidate_all();
148  }
149 
150  iterator
151  begin()
152  { return iterator(_Base::begin(), this); }
153 
155  begin() const
156  { return const_iterator(_Base::begin(), this); }
157 
158  iterator
159  end()
160  { return iterator(_Base::end(), this); }
161 
163  end() const
164  { return const_iterator(_Base::end(), this); }
165 
167  cbegin() const
168  { return const_iterator(_Base::begin(), this); }
169 
171  cend() const
172  { return const_iterator(_Base::end(), this); }
173 
174  // local versions
175  using _Base::begin;
176  using _Base::end;
177  using _Base::cbegin;
178  using _Base::cend;
179 
181  insert(const value_type& __obj)
182  {
183  typedef std::pair<_Base_iterator, bool> __pair_type;
184  __pair_type __res = _Base::insert(__obj);
185  return std::make_pair(iterator(__res.first, this), __res.second);
186  }
187 
188  iterator
189  insert(const_iterator __hint, const value_type& __obj)
190  {
191  __glibcxx_check_insert(__hint);
192  return iterator(_Base::insert(__hint.base(), __obj), this);
193  }
194 
196  insert(value_type&& __obj)
197  {
198  typedef std::pair<typename _Base::iterator, bool> __pair_type;
199  __pair_type __res = _Base::insert(std::move(__obj));
200  return std::make_pair(iterator(__res.first, this), __res.second);
201  }
202 
203  iterator
204  insert(const_iterator __hint, value_type&& __obj)
205  {
206  __glibcxx_check_insert(__hint);
207  return iterator(_Base::insert(__hint.base(), std::move(__obj)), this);
208  }
209 
210  void
212  { _Base::insert(__l); }
213 
214  template<typename _InputIterator>
215  void
216  insert(_InputIterator __first, _InputIterator __last)
217  {
218  __glibcxx_check_valid_range(__first, __last);
219  _Base::insert(__gnu_debug::__base(__first),
220  __gnu_debug::__base(__last));
221  }
222 
223  iterator
224  find(const key_type& __key)
225  { return iterator(_Base::find(__key), this); }
226 
228  find(const key_type& __key) const
229  { return const_iterator(_Base::find(__key), this); }
230 
232  equal_range(const key_type& __key)
233  {
234  typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
235  __pair_type __res = _Base::equal_range(__key);
236  return std::make_pair(iterator(__res.first, this),
237  iterator(__res.second, this));
238  }
239 
241  equal_range(const key_type& __key) const
242  {
244  __res = _Base::equal_range(__key);
245  return std::make_pair(const_iterator(__res.first, this),
246  const_iterator(__res.second, this));
247  }
248 
249  size_type
250  erase(const key_type& __key)
251  {
252  size_type __ret(0);
253  _Base_iterator __victim(_Base::find(__key));
254  if (__victim != _Base::end())
255  {
256  this->_M_invalidate_if(_Equal(__victim));
257  _Base::erase(__victim);
258  __ret = 1;
259  }
260  return __ret;
261  }
262 
263  iterator
264  erase(const_iterator __it)
265  {
266  __glibcxx_check_erase(__it);
267  this->_M_invalidate_if(_Equal(__it.base()));
268  return iterator(_Base::erase(__it.base()), this);
269  }
270 
271  iterator
272  erase(iterator __it)
273  { return erase(const_iterator(__it)); }
274 
275  iterator
276  erase(const_iterator __first, const_iterator __last)
277  {
278  __glibcxx_check_erase_range(__first, __last);
279  for (_Base_const_iterator __tmp = __first.base();
280  __tmp != __last.base(); ++__tmp)
281  {
282  _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
283  _M_message(__gnu_debug::__msg_valid_range)
284  ._M_iterator(__first, "first")
285  ._M_iterator(__last, "last"));
286  this->_M_invalidate_if(_Equal(__tmp));
287  }
288  return iterator(_Base::erase(__first.base(),
289  __last.base()), this);
290  }
291 
292  _Base&
293  _M_base() { return *this; }
294 
295  const _Base&
296  _M_base() const { return *this; }
297 
298  private:
299  void
300  _M_invalidate_all()
301  {
303  this->_M_invalidate_if(_Not_equal(_Base::end()));
304  }
305  };
306 
307  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
308  inline void
311  { __x.swap(__y); }
312 
313  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
314  inline bool
315  operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
317  { return __x._M_equal(__y); }
318 
319  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
320  inline bool
321  operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
322  const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
323  { return !(__x == __y); }
324 
325 
326  /// Class std::unordered_multiset with safety/checking/debug instrumentation.
327  template<typename _Value,
328  typename _Hash = std::hash<_Value>,
329  typename _Pred = std::equal_to<_Value>,
330  typename _Alloc = std::allocator<_Value> >
332  : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>,
333  public __gnu_debug::_Safe_sequence<unordered_multiset<_Value, _Hash,
334  _Pred, _Alloc> >
335  {
336  typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash,
337  _Pred, _Alloc> _Base;
340  typedef typename _Base::iterator _Base_iterator;
342 
343  public:
344  typedef typename _Base::size_type size_type;
345  typedef typename _Base::hasher hasher;
346  typedef typename _Base::key_equal key_equal;
347  typedef typename _Base::allocator_type allocator_type;
348 
349  typedef typename _Base::key_type key_type;
350  typedef typename _Base::value_type value_type;
351 
356 
357  explicit
358  unordered_multiset(size_type __n = 10,
359  const hasher& __hf = hasher(),
360  const key_equal& __eql = key_equal(),
361  const allocator_type& __a = allocator_type())
362  : _Base(__n, __hf, __eql, __a) { }
363 
364  template<typename _InputIterator>
365  unordered_multiset(_InputIterator __first, _InputIterator __last,
366  size_type __n = 0,
367  const hasher& __hf = hasher(),
368  const key_equal& __eql = key_equal(),
369  const allocator_type& __a = allocator_type())
370  : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
371  __last)),
372  __gnu_debug::__base(__last), __n,
373  __hf, __eql, __a), _Safe_base() { }
374 
376  : _Base(__x), _Safe_base() { }
377 
378  unordered_multiset(const _Base& __x)
379  : _Base(__x), _Safe_base() { }
380 
382  : _Base(std::move(__x)), _Safe_base() { }
383 
385  size_type __n = 0,
386  const hasher& __hf = hasher(),
387  const key_equal& __eql = key_equal(),
388  const allocator_type& __a = allocator_type())
389  : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { }
390 
392  operator=(const unordered_multiset& __x)
393  {
394  *static_cast<_Base*>(this) = __x;
395  this->_M_invalidate_all();
396  return *this;
397  }
398 
400  operator=(unordered_multiset&& __x)
401  {
402  // NB: DR 1204.
403  // NB: DR 675.
404  clear();
405  swap(__x);
406  return *this;
407  }
408 
410  operator=(initializer_list<value_type> __l)
411  {
412  this->clear();
413  this->insert(__l);
414  return *this;
415  }
416 
417  void
418  swap(unordered_multiset& __x)
419  {
420  _Base::swap(__x);
421  _Safe_base::_M_swap(__x);
422  }
423 
424  void
425  clear()
426  {
427  _Base::clear();
428  this->_M_invalidate_all();
429  }
430 
431  iterator
432  begin()
433  { return iterator(_Base::begin(), this); }
434 
436  begin() const
437  { return const_iterator(_Base::begin(), this); }
438 
439  iterator
440  end()
441  { return iterator(_Base::end(), this); }
442 
444  end() const
445  { return const_iterator(_Base::end(), this); }
446 
448  cbegin() const
449  { return const_iterator(_Base::begin(), this); }
450 
452  cend() const
453  { return const_iterator(_Base::end(), this); }
454 
455  // local versions
456  using _Base::begin;
457  using _Base::end;
458  using _Base::cbegin;
459  using _Base::cend;
460 
461  iterator
462  insert(const value_type& __obj)
463  { return iterator(_Base::insert(__obj), this); }
464 
465  iterator
466  insert(const_iterator __hint, const value_type& __obj)
467  {
468  __glibcxx_check_insert(__hint);
469  return iterator(_Base::insert(__hint.base(), __obj), this);
470  }
471 
472  iterator
473  insert(value_type&& __obj)
474  { return iterator(_Base::insert(std::move(__obj)), this); }
475 
476  iterator
477  insert(const_iterator __hint, value_type&& __obj)
478  {
479  __glibcxx_check_insert(__hint);
480  return iterator(_Base::insert(__hint.base(), std::move(__obj)), this);
481  }
482 
483  void
485  { _Base::insert(__l); }
486 
487  template<typename _InputIterator>
488  void
489  insert(_InputIterator __first, _InputIterator __last)
490  {
491  __glibcxx_check_valid_range(__first, __last);
492  _Base::insert(__gnu_debug::__base(__first),
493  __gnu_debug::__base(__last));
494  }
495 
496  iterator
497  find(const key_type& __key)
498  { return iterator(_Base::find(__key), this); }
499 
501  find(const key_type& __key) const
502  { return const_iterator(_Base::find(__key), this); }
503 
505  equal_range(const key_type& __key)
506  {
507  typedef std::pair<_Base_iterator, _Base_iterator> __pair_type;
508  __pair_type __res = _Base::equal_range(__key);
509  return std::make_pair(iterator(__res.first, this),
510  iterator(__res.second, this));
511  }
512 
514  equal_range(const key_type& __key) const
515  {
517  __res = _Base::equal_range(__key);
518  return std::make_pair(const_iterator(__res.first, this),
519  const_iterator(__res.second, this));
520  }
521 
522  size_type
523  erase(const key_type& __key)
524  {
525  size_type __ret(0);
527  _Base::equal_range(__key);
528  for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
529  {
530  this->_M_invalidate_if(_Equal(__victim));
531  _Base::erase(__victim++);
532  ++__ret;
533  }
534  return __ret;
535  }
536 
537  iterator
538  erase(const_iterator __it)
539  {
540  __glibcxx_check_erase(__it);
541  this->_M_invalidate_if(_Equal(__it.base()));
542  return iterator(_Base::erase(__it.base()), this);
543  }
544 
545  iterator
546  erase(iterator __it)
547  { return erase(const_iterator(__it)); }
548 
549  iterator
550  erase(const_iterator __first, const_iterator __last)
551  {
552  __glibcxx_check_erase_range(__first, __last);
553  for (_Base_const_iterator __tmp = __first.base();
554  __tmp != __last.base(); ++__tmp)
555  {
556  _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
557  _M_message(__gnu_debug::__msg_valid_range)
558  ._M_iterator(__first, "first")
559  ._M_iterator(__last, "last"));
560  this->_M_invalidate_if(_Equal(__tmp));
561  }
562  return iterator(_Base::erase(__first.base(),
563  __last.base()), this);
564  }
565 
566  _Base&
567  _M_base() { return *this; }
568 
569  const _Base&
570  _M_base() const { return *this; }
571 
572  private:
573  void
574  _M_invalidate_all()
575  {
577  this->_M_invalidate_if(_Not_equal(_Base::end()));
578  }
579  };
580 
581  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
582  inline void
585  { __x.swap(__y); }
586 
587  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
588  inline bool
591  { return __x._M_equal(__y); }
592 
593  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
594  inline bool
595  operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
596  const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
597  { return !(__x == __y); }
598 
599 } // namespace __debug
600 } // namespace std
601 
602 #endif // __GXX_EXPERIMENTAL_CXX0X__
603 
604 #endif