libstdc++
helper_functions.h
Go to the documentation of this file.
1 // Debugging support implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2018 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/helper_functions.h
26  * This file is a GNU debug extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H
30 #define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1
31 
32 #include <bits/stl_iterator_base_types.h> // for iterator_traits,
33  // categories and _Iter_base
34 #include <bits/cpp_type_traits.h> // for __is_integer
35 
36 #include <bits/stl_pair.h> // for pair
37 
38 namespace __gnu_debug
39 {
40  /** The precision to which we can calculate the distance between
41  * two iterators.
42  */
44  {
45  __dp_none, // Not even an iterator type
46  __dp_equality, //< Can compare iterator equality, only
47  __dp_sign, //< Can determine equality and ordering
48  __dp_exact //< Can determine distance precisely
49  };
50 
51  template<typename _Iterator,
52  typename = typename std::__is_integer<_Iterator>::__type>
53  struct _Distance_traits
54  {
55  private:
56  typedef
57  typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
58 
59  template<typename _DiffType,
60  typename = typename std::__is_void<_DiffType>::__type>
61  struct _DiffTraits
62  { typedef _DiffType __type; };
63 
64  template<typename _DiffType>
65  struct _DiffTraits<_DiffType, std::__true_type>
66  { typedef std::ptrdiff_t __type; };
67 
68  typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
69 
70  public:
72  };
73 
74  template<typename _Integral>
75  struct _Distance_traits<_Integral, std::__true_type>
77 
78  /** Determine the distance between two iterators with some known
79  * precision.
80  */
81  template<typename _Iterator>
82  inline typename _Distance_traits<_Iterator>::__type
83  __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
85  { return std::make_pair(__rhs - __lhs, __dp_exact); }
86 
87  template<typename _Iterator>
88  inline typename _Distance_traits<_Iterator>::__type
89  __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
91  {
92  if (__lhs == __rhs)
93  return std::make_pair(0, __dp_exact);
94 
95  return std::make_pair(1, __dp_equality);
96  }
97 
98  template<typename _Iterator>
99  inline typename _Distance_traits<_Iterator>::__type
100  __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
101  { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
102 
103  /** We say that integral types for a valid range, and defer to other
104  * routines to realize what to do with integral types instead of
105  * iterators.
106  */
107  template<typename _Integral>
108  inline bool
109  __valid_range_aux(const _Integral&, const _Integral&,
110  typename _Distance_traits<_Integral>::__type& __dist,
111  std::__true_type)
112  {
113  __dist = std::make_pair(0, __dp_none);
114  return true;
115  }
116 
117  /** We have iterators, so figure out what kind of iterators that are
118  * to see if we can check the range ahead of time.
119  */
120  template<typename _InputIterator>
121  inline bool
122  __valid_range_aux(const _InputIterator& __first,
123  const _InputIterator& __last,
125  std::__false_type)
126  {
127  __dist = __get_distance(__first, __last);
128  switch (__dist.second)
129  {
130  case __dp_none:
131  break;
132  case __dp_equality:
133  if (__dist.first == 0)
134  return true;
135  break;
136  case __dp_sign:
137  case __dp_exact:
138  return __dist.first >= 0;
139  }
140 
141  // Can't tell so assume it is fine.
142  return true;
143  }
144 
145  /** Don't know what these iterators are, or if they are even
146  * iterators (we may get an integral type for InputIterator), so
147  * see if they are integral and pass them on to the next phase
148  * otherwise.
149  */
150  template<typename _InputIterator>
151  inline bool
152  __valid_range(const _InputIterator& __first, const _InputIterator& __last,
154  {
155  typedef typename std::__is_integer<_InputIterator>::__type _Integral;
156  return __valid_range_aux(__first, __last, __dist, _Integral());
157  }
158 
159  template<typename _InputIterator>
160  inline bool
161  __valid_range(const _InputIterator& __first, const _InputIterator& __last)
162  {
163  typename _Distance_traits<_InputIterator>::__type __dist;
164  return __valid_range(__first, __last, __dist);
165  }
166 
167 #if __cplusplus < 201103L
168  // Helper struct to detect random access safe iterators.
169  template<typename _Iterator>
170  struct __is_safe_random_iterator
171  {
172  enum { __value = 0 };
173  typedef std::__false_type __type;
174  };
175 
176  template<typename _Iterator>
177  struct _Siter_base
178  : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
179  { };
180 
181  /** Helper function to extract base iterator of random access safe iterator
182  in order to reduce performance impact of debug mode. Limited to random
183  access iterator because it is the only category for which it is possible
184  to check for correct iterators order in the __valid_range function
185  thanks to the < operator.
186  */
187  template<typename _Iterator>
188  inline typename _Siter_base<_Iterator>::iterator_type
189  __base(_Iterator __it)
190  { return _Siter_base<_Iterator>::_S_base(__it); }
191 #else
192  template<typename _Iterator>
193  inline _Iterator
194  __base(_Iterator __it)
195  { return __it; }
196 #endif
197 
198 #if __cplusplus < 201103L
199  template<typename _Iterator>
200  struct _Unsafe_type
201  { typedef _Iterator _Type; };
202 #endif
203 
204  /* Remove debug mode safe iterator layer, if any. */
205  template<typename _Iterator>
206  inline _Iterator
207  __unsafe(_Iterator __it)
208  { return __it; }
209 }
210 
211 #endif
bool __valid_range_aux(const _Integral &, const _Integral &, typename _Distance_traits< _Integral >::__type &__dist, std::__true_type)
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:208
Marking input iterators.
GNU debug classes for public use.
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:524
ISO C++ entities toplevel namespace is std.
_Distance_traits< _Iterator >::__type __get_distance(const _Iterator &__lhs, const _Iterator &__rhs, std::random_access_iterator_tag)
constexpr iterator_traits< _Iter >::iterator_category __iterator_category(const _Iter &)
bool __valid_range(const _InputIterator &__first, const _InputIterator &__last, typename _Distance_traits< _InputIterator >::__type &__dist)
Random-access iterators support a superset of bidirectional iterator operations.
_T1 first
second_type is the second bound type
Definition: stl_pair.h:214
_T2 second
first is a copy of the first object
Definition: stl_pair.h:215