functions.h

Go to the documentation of this file.
00001 // Debugging support implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
00004 // Free Software Foundation, Inc.
00005 //
00006 // This file is part of the GNU ISO C++ Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 3, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // Under Section 7 of GPL version 3, you are granted additional
00018 // permissions described in the GCC Runtime Library Exception, version
00019 // 3.1, as published by the Free Software Foundation.
00020 
00021 // You should have received a copy of the GNU General Public License and
00022 // a copy of the GCC Runtime Library Exception along with this program;
00023 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00024 // <http://www.gnu.org/licenses/>.
00025 
00026 /** @file debug/functions.h
00027  *  This file is a GNU debug extension to the Standard C++ Library.
00028  */
00029 
00030 #ifndef _GLIBCXX_DEBUG_FUNCTIONS_H
00031 #define _GLIBCXX_DEBUG_FUNCTIONS_H 1
00032 
00033 #include <bits/c++config.h>
00034 #include <bits/stl_iterator_base_types.h> // for iterator_traits, categories
00035 #include <bits/cpp_type_traits.h>         // for __is_integer
00036 
00037 namespace __gnu_debug
00038 {
00039   template<typename _Iterator, typename _Sequence>
00040     class _Safe_iterator;
00041 
00042   // An arbitrary iterator pointer is not singular.
00043   inline bool
00044   __check_singular_aux(const void*) { return false; }
00045 
00046   // We may have an iterator that derives from _Safe_iterator_base but isn't
00047   // a _Safe_iterator.
00048   template<typename _Iterator>
00049     inline bool
00050     __check_singular(_Iterator& __x)
00051     { return __check_singular_aux(&__x); }
00052 
00053   /** Non-NULL pointers are nonsingular. */
00054   template<typename _Tp>
00055     inline bool
00056     __check_singular(const _Tp* __ptr)
00057     { return __ptr == 0; }
00058 
00059   /** Safe iterators know if they are singular. */
00060   template<typename _Iterator, typename _Sequence>
00061     inline bool
00062     __check_singular(const _Safe_iterator<_Iterator, _Sequence>& __x)
00063     { return __x._M_singular(); }
00064 
00065   /** Assume that some arbitrary iterator is dereferenceable, because we
00066       can't prove that it isn't. */
00067   template<typename _Iterator>
00068     inline bool
00069     __check_dereferenceable(_Iterator&)
00070     { return true; }
00071 
00072   /** Non-NULL pointers are dereferenceable. */
00073   template<typename _Tp>
00074     inline bool
00075     __check_dereferenceable(const _Tp* __ptr)
00076     { return __ptr; }
00077 
00078   /** Safe iterators know if they are singular. */
00079   template<typename _Iterator, typename _Sequence>
00080     inline bool
00081     __check_dereferenceable(const _Safe_iterator<_Iterator, _Sequence>& __x)
00082     { return __x._M_dereferenceable(); }
00083 
00084   /** If the distance between two random access iterators is
00085    *  nonnegative, assume the range is valid.
00086   */
00087   template<typename _RandomAccessIterator>
00088     inline bool
00089     __valid_range_aux2(const _RandomAccessIterator& __first,
00090                const _RandomAccessIterator& __last,
00091                std::random_access_iterator_tag)
00092     { return __last - __first >= 0; }
00093 
00094   /** Can't test for a valid range with input iterators, because
00095    *  iteration may be destructive. So we just assume that the range
00096    *  is valid.
00097   */
00098   template<typename _InputIterator>
00099     inline bool
00100     __valid_range_aux2(const _InputIterator&, const _InputIterator&,
00101                std::input_iterator_tag)
00102     { return true; }
00103 
00104   /** We say that integral types for a valid range, and defer to other
00105    *  routines to realize what to do with integral types instead of
00106    *  iterators.
00107   */
00108   template<typename _Integral>
00109     inline bool
00110     __valid_range_aux(const _Integral&, const _Integral&, std::__true_type)
00111     { return true; }
00112 
00113   /** We have iterators, so figure out what kind of iterators that are
00114    *  to see if we can check the range ahead of time.
00115   */
00116   template<typename _InputIterator>
00117     inline bool
00118     __valid_range_aux(const _InputIterator& __first,
00119               const _InputIterator& __last, std::__false_type)
00120   {
00121     typedef typename std::iterator_traits<_InputIterator>::iterator_category
00122       _Category;
00123     return __valid_range_aux2(__first, __last, _Category());
00124   }
00125 
00126   /** Don't know what these iterators are, or if they are even
00127    *  iterators (we may get an integral type for InputIterator), so
00128    *  see if they are integral and pass them on to the next phase
00129    *  otherwise.
00130   */
00131   template<typename _InputIterator>
00132     inline bool
00133     __valid_range(const _InputIterator& __first, const _InputIterator& __last)
00134     {
00135       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
00136       return __valid_range_aux(__first, __last, _Integral());
00137     }
00138 
00139   /** Safe iterators know how to check if they form a valid range. */
00140   template<typename _Iterator, typename _Sequence>
00141     inline bool
00142     __valid_range(const _Safe_iterator<_Iterator, _Sequence>& __first,
00143           const _Safe_iterator<_Iterator, _Sequence>& __last)
00144     { return __first._M_valid_range(__last); }
00145 
00146   /* Checks that [first, last) is a valid range, and then returns
00147    * __first. This routine is useful when we can't use a separate
00148    * assertion statement because, e.g., we are in a constructor.
00149   */
00150   template<typename _InputIterator>
00151     inline _InputIterator
00152     __check_valid_range(const _InputIterator& __first,
00153             const _InputIterator& __last
00154             __attribute__((__unused__)))
00155     {
00156       _GLIBCXX_DEBUG_ASSERT(__valid_range(__first, __last));
00157       return __first;
00158     }
00159 
00160   /** Checks that __s is non-NULL or __n == 0, and then returns __s. */
00161   template<typename _CharT, typename _Integer>
00162     inline const _CharT*
00163     __check_string(const _CharT* __s,
00164            const _Integer& __n __attribute__((__unused__)))
00165     {
00166 #ifdef _GLIBCXX_DEBUG_PEDANTIC
00167       _GLIBCXX_DEBUG_ASSERT(__s != 0 || __n == 0);
00168 #endif
00169       return __s;
00170     }
00171 
00172   /** Checks that __s is non-NULL and then returns __s. */
00173   template<typename _CharT>
00174     inline const _CharT*
00175     __check_string(const _CharT* __s)
00176     {
00177 #ifdef _GLIBCXX_DEBUG_PEDANTIC
00178       _GLIBCXX_DEBUG_ASSERT(__s != 0);
00179 #endif
00180       return __s;
00181     }
00182 
00183   // Can't check if an input iterator sequence is sorted, because we
00184   // can't step through the sequence.
00185   template<typename _InputIterator>
00186     inline bool
00187     __check_sorted_aux(const _InputIterator&, const _InputIterator&,
00188                        std::input_iterator_tag)
00189     { return true; }
00190 
00191   // Can verify if a forward iterator sequence is in fact sorted using
00192   // std::__is_sorted
00193   template<typename _ForwardIterator>
00194     inline bool
00195     __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last,
00196                        std::forward_iterator_tag)
00197     {
00198       if (__first == __last)
00199         return true;
00200 
00201       _ForwardIterator __next = __first;
00202       for (++__next; __next != __last; __first = __next, ++__next)
00203         if (*__next < *__first)
00204           return false;
00205 
00206       return true;
00207     }
00208 
00209   // Can't check if an input iterator sequence is sorted, because we can't step
00210   // through the sequence.
00211   template<typename _InputIterator, typename _Predicate>
00212     inline bool
00213     __check_sorted_aux(const _InputIterator&, const _InputIterator&,
00214                        _Predicate, std::input_iterator_tag)
00215     { return true; }
00216 
00217   // Can verify if a forward iterator sequence is in fact sorted using
00218   // std::__is_sorted
00219   template<typename _ForwardIterator, typename _Predicate>
00220     inline bool
00221     __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last,
00222                        _Predicate __pred, std::forward_iterator_tag)
00223     {
00224       if (__first == __last)
00225         return true;
00226 
00227       _ForwardIterator __next = __first;
00228       for (++__next; __next != __last; __first = __next, ++__next)
00229         if (__pred(*__next, *__first))
00230           return false;
00231 
00232       return true;
00233     }
00234 
00235   // Determine if a sequence is sorted.
00236   template<typename _InputIterator>
00237     inline bool
00238     __check_sorted(const _InputIterator& __first, const _InputIterator& __last)
00239     {
00240       typedef typename std::iterator_traits<_InputIterator>::iterator_category
00241         _Category;
00242 
00243       // Verify that the < operator for elements in the sequence is a
00244       // StrictWeakOrdering by checking that it is irreflexive.
00245       _GLIBCXX_DEBUG_ASSERT(__first == __last || !(*__first < *__first));
00246 
00247       return __check_sorted_aux(__first, __last, _Category());
00248     }
00249 
00250   template<typename _InputIterator, typename _Predicate>
00251     inline bool
00252     __check_sorted(const _InputIterator& __first, const _InputIterator& __last,
00253                    _Predicate __pred)
00254     {
00255       typedef typename std::iterator_traits<_InputIterator>::iterator_category
00256         _Category;
00257 
00258       // Verify that the predicate is StrictWeakOrdering by checking that it
00259       // is irreflexive.
00260       _GLIBCXX_DEBUG_ASSERT(__first == __last || !__pred(*__first, *__first));
00261 
00262       return __check_sorted_aux(__first, __last, __pred, _Category());
00263     }
00264 
00265   template<typename _InputIterator>
00266     inline bool
00267     __check_sorted_set_aux(const _InputIterator& __first,
00268                const _InputIterator& __last,
00269                std::__true_type)
00270     { return __check_sorted(__first, __last); }
00271 
00272   template<typename _InputIterator>
00273     inline bool
00274     __check_sorted_set_aux(const _InputIterator&,
00275                const _InputIterator&,
00276                std::__false_type)
00277     { return true; }
00278 
00279   template<typename _InputIterator, typename _Predicate>
00280     inline bool
00281     __check_sorted_set_aux(const _InputIterator& __first,
00282                const _InputIterator& __last,
00283                _Predicate __pred, std::__true_type)
00284     { return __check_sorted(__first, __last, __pred); }
00285 
00286   template<typename _InputIterator, typename _Predicate>
00287     inline bool
00288     __check_sorted_set_aux(const _InputIterator&,
00289                const _InputIterator&, _Predicate,
00290                std::__false_type)
00291     { return true; }
00292 
00293   // ... special variant used in std::merge, std::includes, std::set_*.
00294   template<typename _InputIterator1, typename _InputIterator2>
00295     inline bool
00296     __check_sorted_set(const _InputIterator1& __first,
00297                const _InputIterator1& __last,
00298                const _InputIterator2&)
00299     {
00300       typedef typename std::iterator_traits<_InputIterator1>::value_type
00301     _ValueType1;
00302       typedef typename std::iterator_traits<_InputIterator2>::value_type
00303     _ValueType2;
00304 
00305       typedef typename std::__are_same<_ValueType1, _ValueType2>::__type
00306     _SameType;
00307       return __check_sorted_set_aux(__first, __last, _SameType());
00308     }
00309 
00310   template<typename _InputIterator1, typename _InputIterator2,
00311        typename _Predicate>
00312     inline bool
00313     __check_sorted_set(const _InputIterator1& __first,
00314                const _InputIterator1& __last,
00315                const _InputIterator2&, _Predicate __pred)
00316     {
00317       typedef typename std::iterator_traits<_InputIterator1>::value_type
00318     _ValueType1;
00319       typedef typename std::iterator_traits<_InputIterator2>::value_type
00320     _ValueType2;
00321 
00322       typedef typename std::__are_same<_ValueType1, _ValueType2>::__type
00323     _SameType;
00324       return __check_sorted_set_aux(__first, __last, __pred, _SameType());
00325    }
00326 
00327   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00328   // 270. Binary search requirements overly strict
00329   // Determine if a sequence is partitioned w.r.t. this element.
00330   template<typename _ForwardIterator, typename _Tp>
00331     inline bool
00332     __check_partitioned_lower(_ForwardIterator __first,
00333                   _ForwardIterator __last, const _Tp& __value)
00334     {
00335       while (__first != __last && *__first < __value)
00336     ++__first;
00337       while (__first != __last && !(*__first < __value))
00338     ++__first;
00339       return __first == __last;
00340     }
00341 
00342   template<typename _ForwardIterator, typename _Tp>
00343     inline bool
00344     __check_partitioned_upper(_ForwardIterator __first,
00345                   _ForwardIterator __last, const _Tp& __value)
00346     {
00347       while (__first != __last && !(__value < *__first))
00348     ++__first;
00349       while (__first != __last && __value < *__first)
00350     ++__first;
00351       return __first == __last;
00352     }
00353 
00354   // Determine if a sequence is partitioned w.r.t. this element.
00355   template<typename _ForwardIterator, typename _Tp, typename _Pred>
00356     inline bool
00357     __check_partitioned_lower(_ForwardIterator __first,
00358                   _ForwardIterator __last, const _Tp& __value,
00359                   _Pred __pred)
00360     {
00361       while (__first != __last && bool(__pred(*__first, __value)))
00362     ++__first;
00363       while (__first != __last && !bool(__pred(*__first, __value)))
00364     ++__first;
00365       return __first == __last;
00366     }
00367 
00368   template<typename _ForwardIterator, typename _Tp, typename _Pred>
00369     inline bool
00370     __check_partitioned_upper(_ForwardIterator __first,
00371                   _ForwardIterator __last, const _Tp& __value,
00372                   _Pred __pred)
00373     {
00374       while (__first != __last && !bool(__pred(__value, *__first)))
00375     ++__first;
00376       while (__first != __last && bool(__pred(__value, *__first)))
00377     ++__first;
00378       return __first == __last;
00379     }
00380 } // namespace __gnu_debug
00381 
00382 #endif