libstdc++
set.h
Go to the documentation of this file.
1 // Debugging set implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2022 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/set.h
26  * This file is a GNU debug extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_DEBUG_SET_H
30 #define _GLIBCXX_DEBUG_SET_H 1
31 
32 #include <debug/safe_sequence.h>
33 #include <debug/safe_container.h>
34 #include <debug/safe_iterator.h>
35 #include <bits/stl_pair.h>
36 
37 namespace std _GLIBCXX_VISIBILITY(default)
38 {
39 namespace __debug
40 {
41  /// Class std::set with safety/checking/debug instrumentation.
42  template<typename _Key, typename _Compare = std::less<_Key>,
43  typename _Allocator = std::allocator<_Key> >
44  class set
46  set<_Key, _Compare, _Allocator>, _Allocator,
47  __gnu_debug::_Safe_node_sequence>,
48  public _GLIBCXX_STD_C::set<_Key,_Compare,_Allocator>
49  {
50  typedef _GLIBCXX_STD_C::set<_Key, _Compare, _Allocator> _Base;
53 
55  typedef typename _Base::iterator _Base_iterator;
57 
58  template<typename _ItT, typename _SeqT, typename _CatT>
59  friend class ::__gnu_debug::_Safe_iterator;
60 
61  // Reference wrapper for base class. Disambiguates set(const _Base&)
62  // from copy constructor by requiring a user-defined conversion.
63  // See PR libstdc++/90102.
64  struct _Base_ref
65  {
66  _Base_ref(const _Base& __r) : _M_ref(__r) { }
67 
68  const _Base& _M_ref;
69  };
70 
71  public:
72  // types:
73  typedef _Key key_type;
74  typedef _Key value_type;
75  typedef _Compare key_compare;
76  typedef _Compare value_compare;
77  typedef _Allocator allocator_type;
78  typedef typename _Base::reference reference;
79  typedef typename _Base::const_reference const_reference;
80 
82  iterator;
85 
86  typedef typename _Base::size_type size_type;
87  typedef typename _Base::difference_type difference_type;
88  typedef typename _Base::pointer pointer;
89  typedef typename _Base::const_pointer const_pointer;
92 
93  // 23.3.3.1 construct/copy/destroy:
94 
95 #if __cplusplus < 201103L
96  set() : _Base() { }
97 
98  set(const set& __x)
99  : _Base(__x) { }
100 
101  ~set() { }
102 #else
103  set() = default;
104  set(const set&) = default;
105  set(set&&) = default;
106 
108  const _Compare& __comp = _Compare(),
109  const allocator_type& __a = allocator_type())
110  : _Base(__l, __comp, __a) { }
111 
112  explicit
113  set(const allocator_type& __a)
114  : _Base(__a) { }
115 
116  set(const set& __x, const __type_identity_t<allocator_type>& __a)
117  : _Base(__x, __a) { }
118 
119  set(set&& __x, const __type_identity_t<allocator_type>& __a)
120  noexcept( noexcept(_Base(std::move(__x), __a)) )
121  : _Safe(std::move(__x), __a),
122  _Base(std::move(__x), __a) { }
123 
124  set(initializer_list<value_type> __l, const allocator_type& __a)
125  : _Base(__l, __a) { }
126 
127  template<typename _InputIterator>
128  set(_InputIterator __first, _InputIterator __last,
129  const allocator_type& __a)
131  __glibcxx_check_valid_constructor_range(__first, __last)),
132  __gnu_debug::__base(__last), __a) { }
133 
134  ~set() = default;
135 #endif
136 
137  explicit set(const _Compare& __comp,
138  const _Allocator& __a = _Allocator())
139  : _Base(__comp, __a) { }
140 
141  template<typename _InputIterator>
142  set(_InputIterator __first, _InputIterator __last,
143  const _Compare& __comp = _Compare(),
144  const _Allocator& __a = _Allocator())
146  __glibcxx_check_valid_constructor_range(__first, __last)),
147  __gnu_debug::__base(__last),
148  __comp, __a) { }
149 
150  set(_Base_ref __x)
151  : _Base(__x._M_ref) { }
152 
153 #if __cplusplus >= 201103L
154  set&
155  operator=(const set&) = default;
156 
157  set&
158  operator=(set&&) = default;
159 
160  set&
161  operator=(initializer_list<value_type> __l)
162  {
163  _Base::operator=(__l);
164  this->_M_invalidate_all();
165  return *this;
166  }
167 #endif
168 
169  using _Base::get_allocator;
170 
171  // iterators:
172  iterator
173  begin() _GLIBCXX_NOEXCEPT
174  { return iterator(_Base::begin(), this); }
175 
177  begin() const _GLIBCXX_NOEXCEPT
178  { return const_iterator(_Base::begin(), this); }
179 
180  iterator
181  end() _GLIBCXX_NOEXCEPT
182  { return iterator(_Base::end(), this); }
183 
185  end() const _GLIBCXX_NOEXCEPT
186  { return const_iterator(_Base::end(), this); }
187 
189  rbegin() _GLIBCXX_NOEXCEPT
190  { return reverse_iterator(end()); }
191 
193  rbegin() const _GLIBCXX_NOEXCEPT
194  { return const_reverse_iterator(end()); }
195 
197  rend() _GLIBCXX_NOEXCEPT
198  { return reverse_iterator(begin()); }
199 
201  rend() const _GLIBCXX_NOEXCEPT
202  { return const_reverse_iterator(begin()); }
203 
204 #if __cplusplus >= 201103L
206  cbegin() const noexcept
207  { return const_iterator(_Base::begin(), this); }
208 
210  cend() const noexcept
211  { return const_iterator(_Base::end(), this); }
212 
214  crbegin() const noexcept
215  { return const_reverse_iterator(end()); }
216 
218  crend() const noexcept
219  { return const_reverse_iterator(begin()); }
220 #endif
221 
222  // capacity:
223  using _Base::empty;
224  using _Base::size;
225  using _Base::max_size;
226 
227  // modifiers:
228 #if __cplusplus >= 201103L
229  template<typename... _Args>
231  emplace(_Args&&... __args)
232  {
233  auto __res = _Base::emplace(std::forward<_Args>(__args)...);
234  return { { __res.first, this }, __res.second };
235  }
236 
237  template<typename... _Args>
238  iterator
239  emplace_hint(const_iterator __pos, _Args&&... __args)
240  {
241  __glibcxx_check_insert(__pos);
242  return
243  {
244  _Base::emplace_hint(__pos.base(), std::forward<_Args>(__args)...),
245  this
246  };
247  }
248 #endif
249 
251  insert(const value_type& __x)
252  {
253  std::pair<_Base_iterator, bool> __res = _Base::insert(__x);
254  return std::pair<iterator, bool>(iterator(__res.first, this),
255  __res.second);
256  }
257 
258 #if __cplusplus >= 201103L
260  insert(value_type&& __x)
261  {
262  auto __res = _Base::insert(std::move(__x));
263  return { { __res.first, this }, __res.second };
264  }
265 #endif
266 
267  iterator
268  insert(const_iterator __position, const value_type& __x)
269  {
270  __glibcxx_check_insert(__position);
271  return iterator(_Base::insert(__position.base(), __x), this);
272  }
273 
274 #if __cplusplus >= 201103L
275  iterator
276  insert(const_iterator __position, value_type&& __x)
277  {
278  __glibcxx_check_insert(__position);
279  return { _Base::insert(__position.base(), std::move(__x)), this };
280  }
281 #endif
282 
283  template <typename _InputIterator>
284  void
285  insert(_InputIterator __first, _InputIterator __last)
286  {
288  __glibcxx_check_valid_range2(__first, __last, __dist);
289 
290  if (__dist.second >= __gnu_debug::__dp_sign)
291  _Base::insert(__gnu_debug::__unsafe(__first),
292  __gnu_debug::__unsafe(__last));
293  else
294  _Base::insert(__first, __last);
295  }
296 
297 #if __cplusplus >= 201103L
298  void
299  insert(initializer_list<value_type> __l)
300  { _Base::insert(__l); }
301 #endif
302 
303 #if __cplusplus > 201402L
304  using node_type = typename _Base::node_type;
306 
307  node_type
308  extract(const_iterator __position)
309  {
310  __glibcxx_check_erase(__position);
311  this->_M_invalidate_if(_Equal(__position.base()));
312  return _Base::extract(__position.base());
313  }
314 
315  node_type
316  extract(const key_type& __key)
317  {
318  const auto __position = find(__key);
319  if (__position != end())
320  return extract(__position);
321  return {};
322  }
323 
325  insert(node_type&& __nh)
326  {
327  auto __ret = _Base::insert(std::move(__nh));
328  iterator __pos = iterator(__ret.position, this);
329  return { __pos, __ret.inserted, std::move(__ret.node) };
330  }
331 
332  iterator
333  insert(const_iterator __hint, node_type&& __nh)
334  {
335  __glibcxx_check_insert(__hint);
336  return { _Base::insert(__hint.base(), std::move(__nh)), this };
337  }
338 
339  using _Base::merge;
340 #endif // C++17
341 
342 #if __cplusplus >= 201103L
343  _GLIBCXX_ABI_TAG_CXX11
344  iterator
345  erase(const_iterator __position)
346  {
347  __glibcxx_check_erase(__position);
348  return { erase(__position.base()), this };
349  }
350 
352  erase(_Base_const_iterator __position)
353  {
354  __glibcxx_check_erase2(__position);
355  this->_M_invalidate_if(_Equal(__position));
356  return _Base::erase(__position);
357  }
358 #else
359  void
360  erase(iterator __position)
361  {
362  __glibcxx_check_erase(__position);
363  this->_M_invalidate_if(_Equal(__position.base()));
364  _Base::erase(__position.base());
365  }
366 #endif
367 
368  size_type
369  erase(const key_type& __x)
370  {
371  _Base_iterator __victim = _Base::find(__x);
372  if (__victim == _Base::end())
373  return 0;
374  else
375  {
376  this->_M_invalidate_if(_Equal(__victim));
377  _Base::erase(__victim);
378  return 1;
379  }
380  }
381 
382 #if __cplusplus >= 201103L
383  _GLIBCXX_ABI_TAG_CXX11
384  iterator
385  erase(const_iterator __first, const_iterator __last)
386  {
387  // _GLIBCXX_RESOLVE_LIB_DEFECTS
388  // 151. can't currently clear() empty container
389  __glibcxx_check_erase_range(__first, __last);
390  for (_Base_const_iterator __victim = __first.base();
391  __victim != __last.base(); ++__victim)
392  {
393  _GLIBCXX_DEBUG_VERIFY(__victim != _Base::cend(),
394  _M_message(__gnu_debug::__msg_valid_range)
395  ._M_iterator(__first, "first")
396  ._M_iterator(__last, "last"));
397  this->_M_invalidate_if(_Equal(__victim));
398  }
399 
400  return { _Base::erase(__first.base(), __last.base()), this };
401  }
402 #else
403  void
404  erase(iterator __first, iterator __last)
405  {
406  // _GLIBCXX_RESOLVE_LIB_DEFECTS
407  // 151. can't currently clear() empty container
408  __glibcxx_check_erase_range(__first, __last);
409  for (_Base_iterator __victim = __first.base();
410  __victim != __last.base(); ++__victim)
411  {
412  _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(),
413  _M_message(__gnu_debug::__msg_valid_range)
414  ._M_iterator(__first, "first")
415  ._M_iterator(__last, "last"));
416  this->_M_invalidate_if(_Equal(__victim));
417  }
418  _Base::erase(__first.base(), __last.base());
419  }
420 #endif
421 
422  void
423  swap(set& __x)
424  _GLIBCXX_NOEXCEPT_IF( noexcept(declval<_Base&>().swap(__x)) )
425  {
426  _Safe::_M_swap(__x);
427  _Base::swap(__x);
428  }
429 
430  void
431  clear() _GLIBCXX_NOEXCEPT
432  {
433  this->_M_invalidate_all();
434  _Base::clear();
435  }
436 
437  // observers:
438  using _Base::key_comp;
439  using _Base::value_comp;
440 
441  // set operations:
442  iterator
443  find(const key_type& __x)
444  { return iterator(_Base::find(__x), this); }
445 
446  // _GLIBCXX_RESOLVE_LIB_DEFECTS
447  // 214. set::find() missing const overload
449  find(const key_type& __x) const
450  { return const_iterator(_Base::find(__x), this); }
451 
452 #if __cplusplus > 201103L
453  template<typename _Kt,
454  typename _Req =
455  typename __has_is_transparent<_Compare, _Kt>::type>
456  iterator
457  find(const _Kt& __x)
458  { return { _Base::find(__x), this }; }
459 
460  template<typename _Kt,
461  typename _Req =
462  typename __has_is_transparent<_Compare, _Kt>::type>
464  find(const _Kt& __x) const
465  { return { _Base::find(__x), this }; }
466 #endif
467 
468  using _Base::count;
469 
470  iterator
471  lower_bound(const key_type& __x)
472  { return iterator(_Base::lower_bound(__x), this); }
473 
474  // _GLIBCXX_RESOLVE_LIB_DEFECTS
475  // 214. set::find() missing const overload
477  lower_bound(const key_type& __x) const
478  { return const_iterator(_Base::lower_bound(__x), this); }
479 
480 #if __cplusplus > 201103L
481  template<typename _Kt,
482  typename _Req =
483  typename __has_is_transparent<_Compare, _Kt>::type>
484  iterator
485  lower_bound(const _Kt& __x)
486  { return { _Base::lower_bound(__x), this }; }
487 
488  template<typename _Kt,
489  typename _Req =
490  typename __has_is_transparent<_Compare, _Kt>::type>
492  lower_bound(const _Kt& __x) const
493  { return { _Base::lower_bound(__x), this }; }
494 #endif
495 
496  iterator
497  upper_bound(const key_type& __x)
498  { return iterator(_Base::upper_bound(__x), this); }
499 
500  // _GLIBCXX_RESOLVE_LIB_DEFECTS
501  // 214. set::find() missing const overload
503  upper_bound(const key_type& __x) const
504  { return const_iterator(_Base::upper_bound(__x), this); }
505 
506 #if __cplusplus > 201103L
507  template<typename _Kt,
508  typename _Req =
509  typename __has_is_transparent<_Compare, _Kt>::type>
510  iterator
511  upper_bound(const _Kt& __x)
512  { return { _Base::upper_bound(__x), this }; }
513 
514  template<typename _Kt,
515  typename _Req =
516  typename __has_is_transparent<_Compare, _Kt>::type>
518  upper_bound(const _Kt& __x) const
519  { return { _Base::upper_bound(__x), this }; }
520 #endif
521 
523  equal_range(const key_type& __x)
524  {
526  _Base::equal_range(__x);
527  return std::make_pair(iterator(__res.first, this),
528  iterator(__res.second, this));
529  }
530 
531  // _GLIBCXX_RESOLVE_LIB_DEFECTS
532  // 214. set::find() missing const overload
534  equal_range(const key_type& __x) const
535  {
537  _Base::equal_range(__x);
538  return std::make_pair(const_iterator(__res.first, this),
539  const_iterator(__res.second, this));
540  }
541 
542 #if __cplusplus > 201103L
543  template<typename _Kt,
544  typename _Req =
545  typename __has_is_transparent<_Compare, _Kt>::type>
547  equal_range(const _Kt& __x)
548  {
549  auto __res = _Base::equal_range(__x);
550  return { { __res.first, this }, { __res.second, this } };
551  }
552 
553  template<typename _Kt,
554  typename _Req =
555  typename __has_is_transparent<_Compare, _Kt>::type>
557  equal_range(const _Kt& __x) const
558  {
559  auto __res = _Base::equal_range(__x);
560  return { { __res.first, this }, { __res.second, this } };
561  }
562 #endif
563 
564  _Base&
565  _M_base() _GLIBCXX_NOEXCEPT { return *this; }
566 
567  const _Base&
568  _M_base() const _GLIBCXX_NOEXCEPT { return *this; }
569  };
570 
571 #if __cpp_deduction_guides >= 201606
572 
573  template<typename _InputIterator,
574  typename _Compare =
576  typename _Allocator =
578  typename = _RequireInputIter<_InputIterator>,
579  typename = _RequireNotAllocator<_Compare>,
580  typename = _RequireAllocator<_Allocator>>
581  set(_InputIterator, _InputIterator,
582  _Compare = _Compare(), _Allocator = _Allocator())
584  _Compare, _Allocator>;
585 
586  template<typename _Key, typename _Compare = less<_Key>,
587  typename _Allocator = allocator<_Key>,
588  typename = _RequireNotAllocator<_Compare>,
589  typename = _RequireAllocator<_Allocator>>
591  _Compare = _Compare(), _Allocator = _Allocator())
593 
594  template<typename _InputIterator, typename _Allocator,
595  typename = _RequireInputIter<_InputIterator>,
596  typename = _RequireAllocator<_Allocator>>
597  set(_InputIterator, _InputIterator, _Allocator)
600  _Allocator>;
601 
602  template<typename _Key, typename _Allocator,
603  typename = _RequireAllocator<_Allocator>>
604  set(initializer_list<_Key>, _Allocator)
605  -> set<_Key, less<_Key>, _Allocator>;
606 
607 #endif // deduction guides
608 
609  template<typename _Key, typename _Compare, typename _Allocator>
610  inline bool
611  operator==(const set<_Key, _Compare, _Allocator>& __lhs,
612  const set<_Key, _Compare, _Allocator>& __rhs)
613  { return __lhs._M_base() == __rhs._M_base(); }
614 
615 #if __cpp_lib_three_way_comparison
616  template<typename _Key, typename _Compare, typename _Alloc>
617  inline __detail::__synth3way_t<_Key>
618  operator<=>(const set<_Key, _Compare, _Alloc>& __lhs,
619  const set<_Key, _Compare, _Alloc>& __rhs)
620  { return __lhs._M_base() <=> __rhs._M_base(); }
621 #else
622  template<typename _Key, typename _Compare, typename _Allocator>
623  inline bool
624  operator!=(const set<_Key, _Compare, _Allocator>& __lhs,
625  const set<_Key, _Compare, _Allocator>& __rhs)
626  { return __lhs._M_base() != __rhs._M_base(); }
627 
628  template<typename _Key, typename _Compare, typename _Allocator>
629  inline bool
630  operator<(const set<_Key, _Compare, _Allocator>& __lhs,
631  const set<_Key, _Compare, _Allocator>& __rhs)
632  { return __lhs._M_base() < __rhs._M_base(); }
633 
634  template<typename _Key, typename _Compare, typename _Allocator>
635  inline bool
636  operator<=(const set<_Key, _Compare, _Allocator>& __lhs,
637  const set<_Key, _Compare, _Allocator>& __rhs)
638  { return __lhs._M_base() <= __rhs._M_base(); }
639 
640  template<typename _Key, typename _Compare, typename _Allocator>
641  inline bool
642  operator>=(const set<_Key, _Compare, _Allocator>& __lhs,
643  const set<_Key, _Compare, _Allocator>& __rhs)
644  { return __lhs._M_base() >= __rhs._M_base(); }
645 
646  template<typename _Key, typename _Compare, typename _Allocator>
647  inline bool
648  operator>(const set<_Key, _Compare, _Allocator>& __lhs,
649  const set<_Key, _Compare, _Allocator>& __rhs)
650  { return __lhs._M_base() > __rhs._M_base(); }
651 #endif // three-way comparison
652 
653  template<typename _Key, typename _Compare, typename _Allocator>
654  void
655  swap(set<_Key, _Compare, _Allocator>& __x,
656  set<_Key, _Compare, _Allocator>& __y)
657  _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y)))
658  { return __x.swap(__y); }
659 
660 } // namespace __debug
661 } // namespace std
662 
663 #endif
#define __glibcxx_check_insert(_Position)
Definition: macros.h:146
#define __glibcxx_check_erase_range(_First, _Last)
Definition: macros.h:248
#define __glibcxx_check_erase(_Position)
Definition: macros.h:212
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:104
ISO C++ entities toplevel namespace is std.
constexpr _Iterator __base(_Iterator __it)
initializer_list
The standard allocator, as per C++03 [20.4.1].
Definition: allocator.h:125
Safe iterator wrapper.
_Iterator & base() noexcept
Return the underlying iterator.
Return type of insert(node_handle&&) on unique maps/sets.
Definition: node_handle.h:382
One of the comparison functors.
Definition: stl_function.h:404
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:187
_T1 first
The first member.
Definition: stl_pair.h:191
_T2 second
The second member.
Definition: stl_pair.h:192
A standard container made up of unique keys, which can be retrieved in logarithmic time.
Definition: stl_set.h:95
void _M_invalidate_if(_Predicate __pred)
Safe class dealing with some allocator dependent operations.
Like _Safe_sequence but with a special _M_invalidate_all implementation not invalidating past-the-end...
Class std::set with safety/checking/debug instrumentation.
Definition: set.h:49