libstdc++
functions.h
Go to the documentation of this file.
1 // Debugging support implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2013 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/c++config.h>
33 #include <bits/stl_iterator_base_types.h> // for iterator_traits, categories and
34  // _Iter_base
35 #include <bits/cpp_type_traits.h> // for __is_integer
36 #include <debug/formatter.h>
37 
38 namespace __gnu_debug
39 {
40  template<typename _Iterator, typename _Sequence>
41  class _Safe_iterator;
42 
43  // An arbitrary iterator pointer is not singular.
44  inline bool
45  __check_singular_aux(const void*) { return false; }
46 
47  // We may have an iterator that derives from _Safe_iterator_base but isn't
48  // a _Safe_iterator.
49  template<typename _Iterator>
50  inline bool
51  __check_singular(_Iterator& __x)
52  { return __check_singular_aux(&__x); }
53 
54  /** Non-NULL pointers are nonsingular. */
55  template<typename _Tp>
56  inline bool
57  __check_singular(const _Tp* __ptr)
58  { return __ptr == 0; }
59 
60  /** Safe iterators know if they are singular. */
61  template<typename _Iterator, typename _Sequence>
62  inline bool
64  { return __x._M_singular(); }
65 
66  /** Assume that some arbitrary iterator is dereferenceable, because we
67  can't prove that it isn't. */
68  template<typename _Iterator>
69  inline bool
71  { return true; }
72 
73  /** Non-NULL pointers are dereferenceable. */
74  template<typename _Tp>
75  inline bool
76  __check_dereferenceable(const _Tp* __ptr)
77  { return __ptr; }
78 
79  /** Safe iterators know if they are singular. */
80  template<typename _Iterator, typename _Sequence>
81  inline bool
83  { return __x._M_dereferenceable(); }
84 
85  /** If the distance between two random access iterators is
86  * nonnegative, assume the range is valid.
87  */
88  template<typename _RandomAccessIterator>
89  inline bool
90  __valid_range_aux2(const _RandomAccessIterator& __first,
91  const _RandomAccessIterator& __last,
93  { return __last - __first >= 0; }
94 
95  /** Can't test for a valid range with input iterators, because
96  * iteration may be destructive. So we just assume that the range
97  * is valid.
98  */
99  template<typename _InputIterator>
100  inline bool
101  __valid_range_aux2(const _InputIterator&, const _InputIterator&,
103  { return true; }
104 
105  /** We say that integral types for a valid range, and defer to other
106  * routines to realize what to do with integral types instead of
107  * iterators.
108  */
109  template<typename _Integral>
110  inline bool
111  __valid_range_aux(const _Integral&, const _Integral&, std::__true_type)
112  { return true; }
113 
114  /** We have iterators, so figure out what kind of iterators that are
115  * to see if we can check the range ahead of time.
116  */
117  template<typename _InputIterator>
118  inline bool
119  __valid_range_aux(const _InputIterator& __first,
120  const _InputIterator& __last, std::__false_type)
121  { return __valid_range_aux2(__first, __last,
122  std::__iterator_category(__first)); }
123 
124  /** Don't know what these iterators are, or if they are even
125  * iterators (we may get an integral type for InputIterator), so
126  * see if they are integral and pass them on to the next phase
127  * otherwise.
128  */
129  template<typename _InputIterator>
130  inline bool
131  __valid_range(const _InputIterator& __first, const _InputIterator& __last)
132  {
133  typedef typename std::__is_integer<_InputIterator>::__type _Integral;
134  return __valid_range_aux(__first, __last, _Integral());
135  }
136 
137  /** Safe iterators know how to check if they form a valid range. */
138  template<typename _Iterator, typename _Sequence>
139  inline bool
142  { return __first._M_valid_range(__last); }
143 
144  /** Safe local iterators know how to check if they form a valid range. */
145  template<typename _Iterator, typename _Sequence>
146  inline bool
149  { return __first._M_valid_range(__last); }
150 
151  /* Checks that [first, last) is a valid range, and then returns
152  * __first. This routine is useful when we can't use a separate
153  * assertion statement because, e.g., we are in a constructor.
154  */
155  template<typename _InputIterator>
156  inline _InputIterator
157  __check_valid_range(const _InputIterator& __first,
158  const _InputIterator& __last
159  __attribute__((__unused__)))
160  {
161  __glibcxx_check_valid_range(__first, __last);
162  return __first;
163  }
164 
165  /** Checks that __s is non-NULL or __n == 0, and then returns __s. */
166  template<typename _CharT, typename _Integer>
167  inline const _CharT*
168  __check_string(const _CharT* __s,
169  const _Integer& __n __attribute__((__unused__)))
170  {
171 #ifdef _GLIBCXX_DEBUG_PEDANTIC
172  __glibcxx_assert(__s != 0 || __n == 0);
173 #endif
174  return __s;
175  }
176 
177  /** Checks that __s is non-NULL and then returns __s. */
178  template<typename _CharT>
179  inline const _CharT*
180  __check_string(const _CharT* __s)
181  {
182 #ifdef _GLIBCXX_DEBUG_PEDANTIC
183  __glibcxx_assert(__s != 0);
184 #endif
185  return __s;
186  }
187 
188  // Can't check if an input iterator sequence is sorted, because we
189  // can't step through the sequence.
190  template<typename _InputIterator>
191  inline bool
192  __check_sorted_aux(const _InputIterator&, const _InputIterator&,
194  { return true; }
195 
196  // Can verify if a forward iterator sequence is in fact sorted using
197  // std::__is_sorted
198  template<typename _ForwardIterator>
199  inline bool
200  __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last,
202  {
203  if (__first == __last)
204  return true;
205 
206  _ForwardIterator __next = __first;
207  for (++__next; __next != __last; __first = __next, ++__next)
208  if (*__next < *__first)
209  return false;
210 
211  return true;
212  }
213 
214  // For performance reason, as the iterator range has been validated, check on
215  // random access safe iterators is done using the base iterator.
216  template<typename _Iterator, typename _Sequence>
217  inline bool
218  __check_sorted_aux(const _Safe_iterator<_Iterator, _Sequence>& __first,
219  const _Safe_iterator<_Iterator, _Sequence>& __last,
221  { return __check_sorted_aux(__first.base(), __last.base(), __tag); }
222 
223  // Can't check if an input iterator sequence is sorted, because we can't step
224  // through the sequence.
225  template<typename _InputIterator, typename _Predicate>
226  inline bool
227  __check_sorted_aux(const _InputIterator&, const _InputIterator&,
228  _Predicate, std::input_iterator_tag)
229  { return true; }
230 
231  // Can verify if a forward iterator sequence is in fact sorted using
232  // std::__is_sorted
233  template<typename _ForwardIterator, typename _Predicate>
234  inline bool
235  __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last,
236  _Predicate __pred, std::forward_iterator_tag)
237  {
238  if (__first == __last)
239  return true;
240 
241  _ForwardIterator __next = __first;
242  for (++__next; __next != __last; __first = __next, ++__next)
243  if (__pred(*__next, *__first))
244  return false;
245 
246  return true;
247  }
248 
249  // For performance reason, as the iterator range has been validated, check on
250  // random access safe iterators is done using the base iterator.
251  template<typename _Iterator, typename _Sequence,
252  typename _Predicate>
253  inline bool
254  __check_sorted_aux(const _Safe_iterator<_Iterator, _Sequence>& __first,
255  const _Safe_iterator<_Iterator, _Sequence>& __last,
256  _Predicate __pred,
258  { return __check_sorted_aux(__first.base(), __last.base(), __pred, __tag); }
259 
260  // Determine if a sequence is sorted.
261  template<typename _InputIterator>
262  inline bool
263  __check_sorted(const _InputIterator& __first, const _InputIterator& __last)
264  {
265  // Verify that the < operator for elements in the sequence is a
266  // StrictWeakOrdering by checking that it is irreflexive.
267  __glibcxx_assert(__first == __last || !(*__first < *__first));
268 
269  return __check_sorted_aux(__first, __last,
270  std::__iterator_category(__first));
271  }
272 
273  template<typename _InputIterator, typename _Predicate>
274  inline bool
275  __check_sorted(const _InputIterator& __first, const _InputIterator& __last,
276  _Predicate __pred)
277  {
278  // Verify that the predicate is StrictWeakOrdering by checking that it
279  // is irreflexive.
280  __glibcxx_assert(__first == __last || !__pred(*__first, *__first));
281 
282  return __check_sorted_aux(__first, __last, __pred,
283  std::__iterator_category(__first));
284  }
285 
286  template<typename _InputIterator>
287  inline bool
288  __check_sorted_set_aux(const _InputIterator& __first,
289  const _InputIterator& __last,
290  std::__true_type)
291  { return __check_sorted(__first, __last); }
292 
293  template<typename _InputIterator>
294  inline bool
295  __check_sorted_set_aux(const _InputIterator&,
296  const _InputIterator&,
297  std::__false_type)
298  { return true; }
299 
300  template<typename _InputIterator, typename _Predicate>
301  inline bool
302  __check_sorted_set_aux(const _InputIterator& __first,
303  const _InputIterator& __last,
304  _Predicate __pred, std::__true_type)
305  { return __check_sorted(__first, __last, __pred); }
306 
307  template<typename _InputIterator, typename _Predicate>
308  inline bool
309  __check_sorted_set_aux(const _InputIterator&,
310  const _InputIterator&, _Predicate,
311  std::__false_type)
312  { return true; }
313 
314  // ... special variant used in std::merge, std::includes, std::set_*.
315  template<typename _InputIterator1, typename _InputIterator2>
316  inline bool
317  __check_sorted_set(const _InputIterator1& __first,
318  const _InputIterator1& __last,
319  const _InputIterator2&)
320  {
321  typedef typename std::iterator_traits<_InputIterator1>::value_type
322  _ValueType1;
323  typedef typename std::iterator_traits<_InputIterator2>::value_type
324  _ValueType2;
325 
326  typedef typename std::__are_same<_ValueType1, _ValueType2>::__type
327  _SameType;
328  return __check_sorted_set_aux(__first, __last, _SameType());
329  }
330 
331  template<typename _InputIterator1, typename _InputIterator2,
332  typename _Predicate>
333  inline bool
334  __check_sorted_set(const _InputIterator1& __first,
335  const _InputIterator1& __last,
336  const _InputIterator2&, _Predicate __pred)
337  {
338  typedef typename std::iterator_traits<_InputIterator1>::value_type
339  _ValueType1;
340  typedef typename std::iterator_traits<_InputIterator2>::value_type
341  _ValueType2;
342 
343  typedef typename std::__are_same<_ValueType1, _ValueType2>::__type
344  _SameType;
345  return __check_sorted_set_aux(__first, __last, __pred, _SameType());
346  }
347 
348  // _GLIBCXX_RESOLVE_LIB_DEFECTS
349  // 270. Binary search requirements overly strict
350  // Determine if a sequence is partitioned w.r.t. this element.
351  template<typename _ForwardIterator, typename _Tp>
352  inline bool
353  __check_partitioned_lower(_ForwardIterator __first,
354  _ForwardIterator __last, const _Tp& __value)
355  {
356  while (__first != __last && *__first < __value)
357  ++__first;
358  if (__first != __last)
359  {
360  ++__first;
361  while (__first != __last && !(*__first < __value))
362  ++__first;
363  }
364  return __first == __last;
365  }
366 
367  template<typename _ForwardIterator, typename _Tp>
368  inline bool
369  __check_partitioned_upper(_ForwardIterator __first,
370  _ForwardIterator __last, const _Tp& __value)
371  {
372  while (__first != __last && !(__value < *__first))
373  ++__first;
374  if (__first != __last)
375  {
376  ++__first;
377  while (__first != __last && __value < *__first)
378  ++__first;
379  }
380  return __first == __last;
381  }
382 
383  // Determine if a sequence is partitioned w.r.t. this element.
384  template<typename _ForwardIterator, typename _Tp, typename _Pred>
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  inline bool
403  __check_partitioned_upper(_ForwardIterator __first,
404  _ForwardIterator __last, const _Tp& __value,
405  _Pred __pred)
406  {
407  while (__first != __last && !bool(__pred(__value, *__first)))
408  ++__first;
409  if (__first != __last)
410  {
411  ++__first;
412  while (__first != __last && bool(__pred(__value, *__first)))
413  ++__first;
414  }
415  return __first == __last;
416  }
417 
418  // Helper struct to detect random access safe iterators.
419  template<typename _Iterator>
420  struct __is_safe_random_iterator
421  {
422  enum { __value = 0 };
423  typedef std::__false_type __type;
424  };
425 
426  template<typename _Iterator, typename _Sequence>
427  struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> >
428  : std::__are_same<std::random_access_iterator_tag,
429  typename std::iterator_traits<_Iterator>::
430  iterator_category>
431  { };
432 
433  template<typename _Iterator>
434  struct _Siter_base
435  : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
436  { };
437 
438  /** Helper function to extract base iterator of random access safe iterator
439  in order to reduce performance impact of debug mode. Limited to random
440  access iterator because it is the only category for which it is possible
441  to check for correct iterators order in the __valid_range function
442  thanks to the < operator.
443  */
444  template<typename _Iterator>
445  inline typename _Siter_base<_Iterator>::iterator_type
446  __base(_Iterator __it)
447  { return _Siter_base<_Iterator>::_S_base(__it); }
448 } // namespace __gnu_debug
449 
450 #endif
Safe iterator wrapper.
Definition: formatter.h:49
_Siter_base< _Iterator >::iterator_type __base(_Iterator __it)
Definition: functions.h:446
bool __check_singular(const _Safe_iterator< _Iterator, _Sequence > &__x)
Definition: functions.h:63
bool __check_dereferenceable(_Iterator &)
Definition: functions.h:70
Random-access iterators support a superset of bidirectional iterator operations.
const _CharT * __check_string(const _CharT *__s, const _Integer &__n __attribute__((__unused__)))
Definition: functions.h:168
bool __valid_range(const _InputIterator &__first, const _InputIterator &__last)
Definition: functions.h:131
iterator_traits< _Iter >::iterator_category __iterator_category(const _Iter &)
bool __valid_range_aux(const _Integral &, const _Integral &, std::__true_type)
Definition: functions.h:111
bool __valid_range_aux2(const _RandomAccessIterator &__first, const _RandomAccessIterator &__last, std::random_access_iterator_tag)
Definition: functions.h:90
Safe iterator wrapper.
Definition: formatter.h:46
Forward iterators support a superset of input iterator operations.
GNU debug classes for public use.
Marking input iterators.
bool _M_dereferenceable() const
Is the iterator dereferenceable?