libstdc++
debug/multiset.h
Go to the documentation of this file.
1 // Debugging multiset implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2014 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/multiset.h
26  * This file is a GNU debug extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_DEBUG_MULTISET_H
30 #define _GLIBCXX_DEBUG_MULTISET_H 1
31 
32 #include <debug/safe_sequence.h>
33 #include <debug/safe_iterator.h>
34 #include <utility>
35 
36 namespace std _GLIBCXX_VISIBILITY(default)
37 {
38 namespace __debug
39 {
40  /// Class std::multiset with safety/checking/debug instrumentation.
41  template<typename _Key, typename _Compare = std::less<_Key>,
42  typename _Allocator = std::allocator<_Key> >
43  class multiset
44  : public _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator>,
45  public __gnu_debug::_Safe_sequence<multiset<_Key, _Compare, _Allocator> >
46  {
47  typedef _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator> _Base;
48 
50  typedef typename _Base::iterator _Base_iterator;
52 
53 #if __cplusplus >= 201103L
54  typedef __gnu_cxx::__alloc_traits<typename
55  _Base::allocator_type> _Alloc_traits;
56 #endif
57  public:
58  // types:
59  typedef _Key key_type;
60  typedef _Key value_type;
61  typedef _Compare key_compare;
62  typedef _Compare value_compare;
63  typedef _Allocator allocator_type;
64  typedef typename _Base::reference reference;
65  typedef typename _Base::const_reference const_reference;
66 
68  iterator;
69  typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
71 
72  typedef typename _Base::size_type size_type;
73  typedef typename _Base::difference_type difference_type;
74  typedef typename _Base::pointer pointer;
75  typedef typename _Base::const_pointer const_pointer;
78 
79  // 23.3.3.1 construct/copy/destroy:
80 
81  multiset() : _Base() { }
82 
83  explicit multiset(const _Compare& __comp,
84  const _Allocator& __a = _Allocator())
85  : _Base(__comp, __a) { }
86 
87  template<typename _InputIterator>
88  multiset(_InputIterator __first, _InputIterator __last,
89  const _Compare& __comp = _Compare(),
90  const _Allocator& __a = _Allocator())
91  : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
92  __last)),
93  __gnu_debug::__base(__last),
94  __comp, __a) { }
95 
96  multiset(const multiset& __x)
97  : _Base(__x) { }
98 
99  multiset(const _Base& __x)
100  : _Base(__x) { }
101 
102 #if __cplusplus >= 201103L
103  multiset(multiset&& __x)
104  noexcept(is_nothrow_copy_constructible<_Compare>::value)
105  : _Base(std::move(__x))
106  { this->_M_swap(__x); }
107 
108  multiset(initializer_list<value_type> __l,
109  const _Compare& __comp = _Compare(),
110  const allocator_type& __a = allocator_type())
111  : _Base(__l, __comp, __a) { }
112 
113  explicit
114  multiset(const allocator_type& __a)
115  : _Base(__a) { }
116 
117  multiset(const multiset& __m, const allocator_type& __a)
118  : _Base(__m, __a) { }
119 
120  multiset(multiset&& __m, const allocator_type& __a)
121  : _Base(std::move(__m._M_base()), __a) { }
122 
123  multiset(initializer_list<value_type> __l, const allocator_type& __a)
124  : _Base(__l, __a)
125  { }
126 
127  template<typename _InputIterator>
128  multiset(_InputIterator __first, _InputIterator __last,
129  const allocator_type& __a)
130  : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
131  __last)),
132  __gnu_debug::__base(__last), __a)
133  { }
134 #endif
135 
136  ~multiset() _GLIBCXX_NOEXCEPT { }
137 
138  multiset&
139  operator=(const multiset& __x)
140  {
141  _M_base() = __x;
142  this->_M_invalidate_all();
143  return *this;
144  }
145 
146 #if __cplusplus >= 201103L
147  multiset&
148  operator=(multiset&& __x)
149  noexcept(_Alloc_traits::_S_nothrow_move())
150  {
151  __glibcxx_check_self_move_assign(__x);
152  bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
153  || __x.get_allocator() == this->get_allocator();
154  _M_base() = std::move(__x._M_base());
155  if (__xfer_memory)
156  this->_M_swap(__x);
157  else
158  this->_M_invalidate_all();
159  __x._M_invalidate_all();
160  return *this;
161  }
162 
163  multiset&
164  operator=(initializer_list<value_type> __l)
165  {
166  _M_base() = __l;
167  this->_M_invalidate_all();
168  return *this;
169  }
170 #endif
171 
172  using _Base::get_allocator;
173 
174  // iterators:
175  iterator
176  begin() _GLIBCXX_NOEXCEPT
177  { return iterator(_Base::begin(), this); }
178 
179  const_iterator
180  begin() const _GLIBCXX_NOEXCEPT
181  { return const_iterator(_Base::begin(), this); }
182 
183  iterator
184  end() _GLIBCXX_NOEXCEPT
185  { return iterator(_Base::end(), this); }
186 
187  const_iterator
188  end() const _GLIBCXX_NOEXCEPT
189  { return const_iterator(_Base::end(), this); }
190 
191  reverse_iterator
192  rbegin() _GLIBCXX_NOEXCEPT
193  { return reverse_iterator(end()); }
194 
195  const_reverse_iterator
196  rbegin() const _GLIBCXX_NOEXCEPT
197  { return const_reverse_iterator(end()); }
198 
199  reverse_iterator
200  rend() _GLIBCXX_NOEXCEPT
201  { return reverse_iterator(begin()); }
202 
203  const_reverse_iterator
204  rend() const _GLIBCXX_NOEXCEPT
205  { return const_reverse_iterator(begin()); }
206 
207 #if __cplusplus >= 201103L
208  const_iterator
209  cbegin() const noexcept
210  { return const_iterator(_Base::begin(), this); }
211 
212  const_iterator
213  cend() const noexcept
214  { return const_iterator(_Base::end(), this); }
215 
216  const_reverse_iterator
217  crbegin() const noexcept
218  { return const_reverse_iterator(end()); }
219 
220  const_reverse_iterator
221  crend() const noexcept
222  { return const_reverse_iterator(begin()); }
223 #endif
224 
225  // capacity:
226  using _Base::empty;
227  using _Base::size;
228  using _Base::max_size;
229 
230  // modifiers:
231 #if __cplusplus >= 201103L
232  template<typename... _Args>
233  iterator
234  emplace(_Args&&... __args)
235  {
236  return iterator(_Base::emplace(std::forward<_Args>(__args)...), this);
237  }
238 
239  template<typename... _Args>
240  iterator
241  emplace_hint(const_iterator __pos, _Args&&... __args)
242  {
243  __glibcxx_check_insert(__pos);
244  return iterator(_Base::emplace_hint(__pos.base(),
245  std::forward<_Args>(__args)...),
246  this);
247  }
248 #endif
249 
250  iterator
251  insert(const value_type& __x)
252  { return iterator(_Base::insert(__x), this); }
253 
254 #if __cplusplus >= 201103L
255  iterator
256  insert(value_type&& __x)
257  { return iterator(_Base::insert(std::move(__x)), this); }
258 #endif
259 
260  iterator
261  insert(const_iterator __position, const value_type& __x)
262  {
263  __glibcxx_check_insert(__position);
264  return iterator(_Base::insert(__position.base(), __x), this);
265  }
266 
267 #if __cplusplus >= 201103L
268  iterator
269  insert(const_iterator __position, value_type&& __x)
270  {
271  __glibcxx_check_insert(__position);
272  return iterator(_Base::insert(__position.base(), std::move(__x)),
273  this);
274  }
275 #endif
276 
277  template<typename _InputIterator>
278  void
279  insert(_InputIterator __first, _InputIterator __last)
280  {
281  __glibcxx_check_valid_range(__first, __last);
282  _Base::insert(__gnu_debug::__base(__first),
283  __gnu_debug::__base(__last));
284  }
285 
286 #if __cplusplus >= 201103L
287  void
288  insert(initializer_list<value_type> __l)
289  { _Base::insert(__l); }
290 #endif
291 
292 #if __cplusplus >= 201103L
293  iterator
294  erase(const_iterator __position)
295  {
296  __glibcxx_check_erase(__position);
297  this->_M_invalidate_if(_Equal(__position.base()));
298  return iterator(_Base::erase(__position.base()), this);
299  }
300 #else
301  void
302  erase(iterator __position)
303  {
304  __glibcxx_check_erase(__position);
305  this->_M_invalidate_if(_Equal(__position.base()));
306  _Base::erase(__position.base());
307  }
308 #endif
309 
310  size_type
311  erase(const key_type& __x)
312  {
314  _Base::equal_range(__x);
315  size_type __count = 0;
316  _Base_iterator __victim = __victims.first;
317  while (__victim != __victims.second)
318  {
319  this->_M_invalidate_if(_Equal(__victim));
320  _Base::erase(__victim++);
321  ++__count;
322  }
323  return __count;
324  }
325 
326 #if __cplusplus >= 201103L
327  iterator
328  erase(const_iterator __first, const_iterator __last)
329  {
330  // _GLIBCXX_RESOLVE_LIB_DEFECTS
331  // 151. can't currently clear() empty container
332  __glibcxx_check_erase_range(__first, __last);
333  for (_Base_const_iterator __victim = __first.base();
334  __victim != __last.base(); ++__victim)
335  {
336  _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
337  _M_message(__gnu_debug::__msg_valid_range)
338  ._M_iterator(__first, "first")
339  ._M_iterator(__last, "last"));
340  this->_M_invalidate_if(_Equal(__victim));
341  }
342  return iterator(_Base::erase(__first.base(), __last.base()), this);
343  }
344 #else
345  void
346  erase(iterator __first, iterator __last)
347  {
348  // _GLIBCXX_RESOLVE_LIB_DEFECTS
349  // 151. can't currently clear() empty container
350  __glibcxx_check_erase_range(__first, __last);
351  for (_Base_iterator __victim = __first.base();
352  __victim != __last.base(); ++__victim)
353  {
354  _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
355  _M_message(__gnu_debug::__msg_valid_range)
356  ._M_iterator(__first, "first")
357  ._M_iterator(__last, "last"));
358  this->_M_invalidate_if(_Equal(__victim));
359  }
360  _Base::erase(__first.base(), __last.base());
361  }
362 #endif
363 
364  void
365  swap(multiset& __x)
366 #if __cplusplus >= 201103L
367  noexcept(_Alloc_traits::_S_nothrow_swap())
368 #endif
369  {
370 #if __cplusplus >= 201103L
371  if (!_Alloc_traits::_S_propagate_on_swap())
372  __glibcxx_check_equal_allocs(__x);
373 #endif
374  _Base::swap(__x);
375  this->_M_swap(__x);
376  }
377 
378  void
379  clear() _GLIBCXX_NOEXCEPT
380  {
381  this->_M_invalidate_all();
382  _Base::clear();
383  }
384 
385  // observers:
386  using _Base::key_comp;
387  using _Base::value_comp;
388 
389  // multiset operations:
390  iterator
391  find(const key_type& __x)
392  { return iterator(_Base::find(__x), this); }
393 
394  // _GLIBCXX_RESOLVE_LIB_DEFECTS
395  // 214. set::find() missing const overload
396  const_iterator
397  find(const key_type& __x) const
398  { return const_iterator(_Base::find(__x), this); }
399 
400  using _Base::count;
401 
402  iterator
403  lower_bound(const key_type& __x)
404  { return iterator(_Base::lower_bound(__x), this); }
405 
406  // _GLIBCXX_RESOLVE_LIB_DEFECTS
407  // 214. set::find() missing const overload
408  const_iterator
409  lower_bound(const key_type& __x) const
410  { return const_iterator(_Base::lower_bound(__x), this); }
411 
412  iterator
413  upper_bound(const key_type& __x)
414  { return iterator(_Base::upper_bound(__x), this); }
415 
416  // _GLIBCXX_RESOLVE_LIB_DEFECTS
417  // 214. set::find() missing const overload
418  const_iterator
419  upper_bound(const key_type& __x) const
420  { return const_iterator(_Base::upper_bound(__x), this); }
421 
423  equal_range(const key_type& __x)
424  {
426  _Base::equal_range(__x);
427  return std::make_pair(iterator(__res.first, this),
428  iterator(__res.second, this));
429  }
430 
431  // _GLIBCXX_RESOLVE_LIB_DEFECTS
432  // 214. set::find() missing const overload
434  equal_range(const key_type& __x) const
435  {
437  _Base::equal_range(__x);
438  return std::make_pair(const_iterator(__res.first, this),
439  const_iterator(__res.second, this));
440  }
441 
442  _Base&
443  _M_base() _GLIBCXX_NOEXCEPT { return *this; }
444 
445  const _Base&
446  _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
447 
448  private:
449  void
450  _M_invalidate_all()
451  {
453  this->_M_invalidate_if(_Not_equal(_Base::end()));
454  }
455  };
456 
457  template<typename _Key, typename _Compare, typename _Allocator>
458  inline bool
459  operator==(const multiset<_Key, _Compare, _Allocator>& __lhs,
461  { return __lhs._M_base() == __rhs._M_base(); }
462 
463  template<typename _Key, typename _Compare, typename _Allocator>
464  inline bool
465  operator!=(const multiset<_Key, _Compare, _Allocator>& __lhs,
467  { return __lhs._M_base() != __rhs._M_base(); }
468 
469  template<typename _Key, typename _Compare, typename _Allocator>
470  inline bool
471  operator<(const multiset<_Key, _Compare, _Allocator>& __lhs,
472  const multiset<_Key, _Compare, _Allocator>& __rhs)
473  { return __lhs._M_base() < __rhs._M_base(); }
474 
475  template<typename _Key, typename _Compare, typename _Allocator>
476  inline bool
477  operator<=(const multiset<_Key, _Compare, _Allocator>& __lhs,
478  const multiset<_Key, _Compare, _Allocator>& __rhs)
479  { return __lhs._M_base() <= __rhs._M_base(); }
480 
481  template<typename _Key, typename _Compare, typename _Allocator>
482  inline bool
483  operator>=(const multiset<_Key, _Compare, _Allocator>& __lhs,
484  const multiset<_Key, _Compare, _Allocator>& __rhs)
485  { return __lhs._M_base() >= __rhs._M_base(); }
486 
487  template<typename _Key, typename _Compare, typename _Allocator>
488  inline bool
489  operator>(const multiset<_Key, _Compare, _Allocator>& __lhs,
490  const multiset<_Key, _Compare, _Allocator>& __rhs)
491  { return __lhs._M_base() > __rhs._M_base(); }
492 
493  template<typename _Key, typename _Compare, typename _Allocator>
494  void
495  swap(multiset<_Key, _Compare, _Allocator>& __x,
496  multiset<_Key, _Compare, _Allocator>& __y)
497  { return __x.swap(__y); }
498 
499 } // namespace __debug
500 } // namespace std
501 
502 #endif
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:101
constexpr pair< typename __decay_and_strip< _T1 >::__type, typename __decay_and_strip< _T2 >::__type > make_pair(_T1 &&__x, _T2 &&__y)
A convenience wrapper for creating a pair from two objects.
Definition: stl_pair.h:276
Uniform interface to C++98 and C++0x allocators.
#define __glibcxx_check_insert(_Position)
Definition: macros.h:73
Base class for constructing a safe sequence type that tracks iterators that reference it...
Definition: formatter.h:52
_Siter_base< _Iterator >::iterator_type __base(_Iterator __it)
Definition: functions.h:558
void _M_swap(_Safe_sequence_base &__x)
_T1 first
second_type is the second bound type
Definition: stl_pair.h:101
ISO C++ entities toplevel namespace is std.
#define __glibcxx_check_erase(_Position)
Definition: macros.h:139
Safe iterator wrapper.
Definition: formatter.h:46
Class std::multiset with safety/checking/debug instrumentation.
bool operator>=(const basic_string< _CharT, _Traits, _Alloc > &__lhs, const basic_string< _CharT, _Traits, _Alloc > &__rhs)
Test if string doesn't precede string.
A standard container made up of elements, which can be retrieved in logarithmic time.
Definition: stl_multiset.h:92
bool operator>(const basic_string< _CharT, _Traits, _Alloc > &__lhs, const basic_string< _CharT, _Traits, _Alloc > &__rhs)
Test if string follows string.
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:96
void swap(_Tp &, _Tp &) noexcept(__and_< is_nothrow_move_constructible< _Tp >, is_nothrow_move_assignable< _Tp >>::value)
Swaps two values.
Definition: move.h:166
_Iterator base() const noexcept
Return the underlying iterator.
_T2 second
first is a copy of the first object
Definition: stl_pair.h:102
#define __glibcxx_check_erase_range(_First, _Last)
Definition: macros.h:167