libstdc++
functions.h
Go to the documentation of this file.
1 // Debugging support implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2020 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/functions.h
26  * This file is a GNU debug extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_DEBUG_FUNCTIONS_H
30 #define _GLIBCXX_DEBUG_FUNCTIONS_H 1
31 
32 #include <bits/stl_function.h> // for less
33 
34 #if __cplusplus >= 201103L
35 # include <bits/stl_iterator.h> // for __miter_base
36 # include <type_traits> // for is_lvalue_reference and conditional.
37 #endif
38 
39 #include <debug/helper_functions.h>
40 #include <debug/formatter.h>
41 
42 namespace __gnu_debug
43 {
44  template<typename _Sequence>
45  struct _Insert_range_from_self_is_safe
46  { enum { __value = 0 }; };
47 
48  template<typename _Sequence>
49  struct _Is_contiguous_sequence : std::__false_type { };
50 
51  /* Checks that [first, last) is a valid range, and then returns
52  * __first. This routine is useful when we can't use a separate
53  * assertion statement because, e.g., we are in a constructor.
54  */
55  template<typename _InputIterator>
56  inline _InputIterator
57  __check_valid_range(const _InputIterator& __first,
58  const _InputIterator& __last,
59  const char* __file,
60  unsigned int __line,
61  const char* __function)
62  {
63  __glibcxx_check_valid_range_at(__first, __last,
64  __file, __line, __function);
65  return __first;
66  }
67 
68  /* Handle the case where __other is a pointer to _Sequence::value_type. */
69  template<typename _Iterator, typename _Sequence, typename _Category>
70  inline bool
71  __foreign_iterator_aux4(
72  const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
73  const typename _Sequence::value_type* __other)
74  {
75  typedef const typename _Sequence::value_type* _PointerType;
76  typedef std::less<_PointerType> _Less;
77 #if __cplusplus >= 201103L
78  constexpr _Less __l{};
79 #else
80  const _Less __l = _Less();
81 #endif
82  const _Sequence* __seq = __it._M_get_sequence();
83  const _PointerType __begin = std::__addressof(*__seq->_M_base().begin());
84  const _PointerType __end = std::__addressof(*(__seq->_M_base().end()-1));
85 
86  // Check whether __other points within the contiguous storage.
87  return __l(__other, __begin) || __l(__end, __other);
88  }
89 
90  /* Fallback overload for when we can't tell, assume it is valid. */
91  template<typename _Iterator, typename _Sequence, typename _Category>
92  inline bool
93  __foreign_iterator_aux4(
94  const _Safe_iterator<_Iterator, _Sequence, _Category>&, ...)
95  { return true; }
96 
97  /* Handle sequences with contiguous storage */
98  template<typename _Iterator, typename _Sequence, typename _Category,
99  typename _InputIterator>
100  inline bool
101  __foreign_iterator_aux3(
102  const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
103  const _InputIterator& __other, const _InputIterator& __other_end,
104  std::__true_type)
105  {
106  if (__other == __other_end)
107  return true; // inserting nothing is safe even if not foreign iters
108  if (__it._M_get_sequence()->empty())
109  return true; // can't be self-inserting if self is empty
110  return __foreign_iterator_aux4(__it, std::__addressof(*__other));
111  }
112 
113  /* Handle non-contiguous containers, assume it is valid. */
114  template<typename _Iterator, typename _Sequence, typename _Category,
115  typename _InputIterator>
116  inline bool
117  __foreign_iterator_aux3(
118  const _Safe_iterator<_Iterator, _Sequence, _Category>&,
119  const _InputIterator&, const _InputIterator&,
120  std::__false_type)
121  { return true; }
122 
123  /** Handle debug iterators from the same type of container. */
124  template<typename _Iterator, typename _Sequence, typename _Category,
125  typename _OtherIterator>
126  inline bool
131  { return __it._M_get_sequence() != __other._M_get_sequence(); }
132 
133  /** Handle debug iterators from different types of container. */
134  template<typename _Iterator, typename _Sequence, typename _Category,
135  typename _OtherIterator, typename _OtherSequence,
136  typename _OtherCategory>
137  inline bool
140  const _Safe_iterator<_OtherIterator, _OtherSequence,
141  _OtherCategory>&,
142  const _Safe_iterator<_OtherIterator, _OtherSequence,
143  _OtherCategory>&)
144  { return true; }
145 
146  /* Handle non-debug iterators. */
147  template<typename _Iterator, typename _Sequence, typename _Category,
148  typename _InputIterator>
149  inline bool
151  const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
152  const _InputIterator& __other,
153  const _InputIterator& __other_end)
154  {
155 #if __cplusplus < 201103L
156  typedef _Is_contiguous_sequence<_Sequence> __tag;
157 #else
158  using __lvalref = std::is_lvalue_reference<
160  using __contiguous = _Is_contiguous_sequence<_Sequence>;
161  using __tag = typename std::conditional<__lvalref::value, __contiguous,
162  std::__false_type>::type;
163 #endif
164  return __foreign_iterator_aux3(__it, __other, __other_end, __tag());
165  }
166 
167  /* Handle the case where we aren't really inserting a range after all */
168  template<typename _Iterator, typename _Sequence, typename _Category,
169  typename _Integral>
170  inline bool
171  __foreign_iterator_aux(
172  const _Safe_iterator<_Iterator, _Sequence, _Category>&,
173  _Integral, _Integral, std::__true_type)
174  { return true; }
175 
176  /* Handle all iterators. */
177  template<typename _Iterator, typename _Sequence, typename _Category,
178  typename _InputIterator>
179  inline bool
180  __foreign_iterator_aux(
181  const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
182  _InputIterator __other, _InputIterator __other_end,
183  std::__false_type)
184  {
185  return _Insert_range_from_self_is_safe<_Sequence>::__value
186  || __foreign_iterator_aux2(__it, std::__miter_base(__other),
187  std::__miter_base(__other_end));
188  }
189 
190  template<typename _Iterator, typename _Sequence, typename _Category,
191  typename _InputIterator>
192  inline bool
193  __foreign_iterator(
194  const _Safe_iterator<_Iterator, _Sequence, _Category>& __it,
195  _InputIterator __other, _InputIterator __other_end)
196  {
197  typedef typename std::__is_integer<_InputIterator>::__type _Integral;
198  return __foreign_iterator_aux(__it, __other, __other_end, _Integral());
199  }
200 
201  // Can't check if an input iterator sequence is sorted, because we
202  // can't step through the sequence.
203  template<typename _InputIterator>
204  _GLIBCXX20_CONSTEXPR
205  inline bool
206  __check_sorted_aux(const _InputIterator&, const _InputIterator&,
208  { return true; }
209 
210  // Can verify if a forward iterator sequence is in fact sorted using
211  // std::__is_sorted
212  template<typename _ForwardIterator>
213  _GLIBCXX20_CONSTEXPR
214  inline bool
215  __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last,
217  {
218  if (__first == __last)
219  return true;
220 
221  _ForwardIterator __next = __first;
222  for (++__next; __next != __last; __first = __next, (void)++__next)
223  if (*__next < *__first)
224  return false;
225 
226  return true;
227  }
228 
229  // Can't check if an input iterator sequence is sorted, because we can't step
230  // through the sequence.
231  template<typename _InputIterator, typename _Predicate>
232  _GLIBCXX20_CONSTEXPR
233  inline bool
234  __check_sorted_aux(const _InputIterator&, const _InputIterator&,
235  _Predicate, std::input_iterator_tag)
236  { return true; }
237 
238  // Can verify if a forward iterator sequence is in fact sorted using
239  // std::__is_sorted
240  template<typename _ForwardIterator, typename _Predicate>
241  _GLIBCXX20_CONSTEXPR
242  inline bool
243  __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last,
244  _Predicate __pred, std::forward_iterator_tag)
245  {
246  if (__first == __last)
247  return true;
248 
249  _ForwardIterator __next = __first;
250  for (++__next; __next != __last; __first = __next, (void)++__next)
251  if (__pred(*__next, *__first))
252  return false;
253 
254  return true;
255  }
256 
257  // Determine if a sequence is sorted.
258  template<typename _InputIterator>
259  _GLIBCXX20_CONSTEXPR
260  inline bool
261  __check_sorted(const _InputIterator& __first, const _InputIterator& __last)
262  {
263  return __check_sorted_aux(__first, __last,
264  std::__iterator_category(__first));
265  }
266 
267  template<typename _InputIterator, typename _Predicate>
268  _GLIBCXX20_CONSTEXPR
269  inline bool
270  __check_sorted(const _InputIterator& __first, const _InputIterator& __last,
271  _Predicate __pred)
272  {
273  return __check_sorted_aux(__first, __last, __pred,
274  std::__iterator_category(__first));
275  }
276 
277  template<typename _InputIterator>
278  _GLIBCXX20_CONSTEXPR
279  inline bool
280  __check_sorted_set_aux(const _InputIterator& __first,
281  const _InputIterator& __last,
282  std::__true_type)
283  { return __check_sorted(__first, __last); }
284 
285  template<typename _InputIterator>
286  _GLIBCXX20_CONSTEXPR
287  inline bool
288  __check_sorted_set_aux(const _InputIterator&,
289  const _InputIterator&,
290  std::__false_type)
291  { return true; }
292 
293  template<typename _InputIterator, typename _Predicate>
294  _GLIBCXX20_CONSTEXPR
295  inline bool
296  __check_sorted_set_aux(const _InputIterator& __first,
297  const _InputIterator& __last,
298  _Predicate __pred, std::__true_type)
299  { return __check_sorted(__first, __last, __pred); }
300 
301  template<typename _InputIterator, typename _Predicate>
302  _GLIBCXX20_CONSTEXPR
303  inline bool
304  __check_sorted_set_aux(const _InputIterator&,
305  const _InputIterator&, _Predicate,
306  std::__false_type)
307  { return true; }
308 
309  // ... special variant used in std::merge, std::includes, std::set_*.
310  template<typename _InputIterator1, typename _InputIterator2>
311  _GLIBCXX20_CONSTEXPR
312  inline bool
313  __check_sorted_set(const _InputIterator1& __first,
314  const _InputIterator1& __last,
315  const _InputIterator2&)
316  {
318  _ValueType1;
320  _ValueType2;
321 
322  typedef typename std::__are_same<_ValueType1, _ValueType2>::__type
323  _SameType;
324  return __check_sorted_set_aux(__first, __last, _SameType());
325  }
326 
327  template<typename _InputIterator1, typename _InputIterator2,
328  typename _Predicate>
329  _GLIBCXX20_CONSTEXPR
330  inline bool
331  __check_sorted_set(const _InputIterator1& __first,
332  const _InputIterator1& __last,
333  const _InputIterator2&, _Predicate __pred)
334  {
336  _ValueType1;
338  _ValueType2;
339 
340  typedef typename std::__are_same<_ValueType1, _ValueType2>::__type
341  _SameType;
342  return __check_sorted_set_aux(__first, __last, __pred, _SameType());
343  }
344 
345  // _GLIBCXX_RESOLVE_LIB_DEFECTS
346  // 270. Binary search requirements overly strict
347  // Determine if a sequence is partitioned w.r.t. this element.
348  template<typename _ForwardIterator, typename _Tp>
349  _GLIBCXX20_CONSTEXPR
350  inline bool
351  __check_partitioned_lower(_ForwardIterator __first,
352  _ForwardIterator __last, const _Tp& __value)
353  {
354  while (__first != __last && *__first < __value)
355  ++__first;
356  if (__first != __last)
357  {
358  ++__first;
359  while (__first != __last && !(*__first < __value))
360  ++__first;
361  }
362  return __first == __last;
363  }
364 
365  template<typename _ForwardIterator, typename _Tp>
366  _GLIBCXX20_CONSTEXPR
367  inline bool
368  __check_partitioned_upper(_ForwardIterator __first,
369  _ForwardIterator __last, const _Tp& __value)
370  {
371  while (__first != __last && !(__value < *__first))
372  ++__first;
373  if (__first != __last)
374  {
375  ++__first;
376  while (__first != __last && __value < *__first)
377  ++__first;
378  }
379  return __first == __last;
380  }
381 
382  // Determine if a sequence is partitioned w.r.t. this element.
383  template<typename _ForwardIterator, typename _Tp, typename _Pred>
384  _GLIBCXX20_CONSTEXPR
385  inline bool
386  __check_partitioned_lower(_ForwardIterator __first,
387  _ForwardIterator __last, const _Tp& __value,
388  _Pred __pred)
389  {
390  while (__first != __last && bool(__pred(*__first, __value)))
391  ++__first;
392  if (__first != __last)
393  {
394  ++__first;
395  while (__first != __last && !bool(__pred(*__first, __value)))
396  ++__first;
397  }
398  return __first == __last;
399  }
400 
401  template<typename _ForwardIterator, typename _Tp, typename _Pred>
402  _GLIBCXX20_CONSTEXPR
403  inline bool
404  __check_partitioned_upper(_ForwardIterator __first,
405  _ForwardIterator __last, const _Tp& __value,
406  _Pred __pred)
407  {
408  while (__first != __last && !bool(__pred(__value, *__first)))
409  ++__first;
410  if (__first != __last)
411  {
412  ++__first;
413  while (__first != __last && bool(__pred(__value, *__first)))
414  ++__first;
415  }
416  return __first == __last;
417  }
418 
419 #if __cplusplus >= 201103L
420  struct _Irreflexive_checker
421  {
422  template<typename _It>
424  __ref();
425 
426  template<typename _It,
427  typename = decltype(__ref<_It>() < __ref<_It>())>
428  _GLIBCXX20_CONSTEXPR
429  static bool
430  _S_is_valid(_It __it)
431  { return !(*__it < *__it); }
432 
433  // Fallback method if operator doesn't exist.
434  template<typename... _Args>
435  _GLIBCXX20_CONSTEXPR
436  static bool
437  _S_is_valid(_Args...)
438  { return true; }
439 
440  template<typename _It, typename _Pred, typename
441  = decltype(std::declval<_Pred>()(__ref<_It>(), __ref<_It>()))>
442  _GLIBCXX20_CONSTEXPR
443  static bool
444  _S_is_valid_pred(_It __it, _Pred __pred)
445  { return !__pred(*__it, *__it); }
446 
447  // Fallback method if predicate can't be invoked.
448  template<typename... _Args>
449  _GLIBCXX20_CONSTEXPR
450  static bool
451  _S_is_valid_pred(_Args...)
452  { return true; }
453  };
454 
455  template<typename _Iterator>
456  _GLIBCXX20_CONSTEXPR
457  inline bool
458  __is_irreflexive(_Iterator __it)
459  { return _Irreflexive_checker::_S_is_valid(__it); }
460 
461  template<typename _Iterator, typename _Pred>
462  _GLIBCXX20_CONSTEXPR
463  inline bool
464  __is_irreflexive_pred(_Iterator __it, _Pred __pred)
465  { return _Irreflexive_checker::_S_is_valid_pred(__it, __pred); }
466 #endif
467 
468 } // namespace __gnu_debug
469 
470 #endif
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:49
constexpr iterator_traits< _Iter >::iterator_category __iterator_category(const _Iter &)
GNU debug classes for public use.
bool __foreign_iterator_aux2(const _Safe_iterator< _Iterator, _Sequence, _Category > &__it, const _Safe_iterator< _OtherIterator, _Sequence, _Category > &__other, const _Safe_iterator< _OtherIterator, _Sequence, _Category > &)
Definition: functions.h:127
Define a member typedef type to one of two argument types.
Definition: type_traits:2201
is_lvalue_reference
Definition: type_traits:427
Traits class for iterators.
One of the comparison functors.
Definition: stl_function.h:382
Marking input iterators.
Forward iterators support a superset of input iterator operations.
Safe iterator wrapper.