libstdc++
helper_functions.h
Go to the documentation of this file.
00001 // Debugging support implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2003-2016 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file debug/helper_functions.h
00026  *  This file is a GNU debug extension to the Standard C++ Library.
00027  */
00028 
00029 #ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H
00030 #define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1
00031 
00032 #include <bits/stl_iterator_base_types.h>       // for iterator_traits,
00033                                                 // categories and _Iter_base
00034 #include <bits/cpp_type_traits.h>               // for __is_integer
00035 
00036 #include <bits/stl_pair.h>                      // for pair
00037 
00038 namespace __gnu_debug
00039 {
00040   /** The precision to which we can calculate the distance between
00041    *  two iterators.
00042    */
00043   enum _Distance_precision
00044     {
00045       __dp_none,        // Not even an iterator type
00046       __dp_equality,    //< Can compare iterator equality, only
00047       __dp_sign,        //< Can determine equality and ordering
00048       __dp_exact        //< Can determine distance precisely
00049     };
00050 
00051   template<typename _Iterator,
00052            typename = typename std::__is_integer<_Iterator>::__type>
00053     struct _Distance_traits
00054     {
00055     private:
00056       typedef
00057       typename std::iterator_traits<_Iterator>::difference_type _ItDiffType;
00058 
00059       template<typename _DiffType,
00060                typename = typename std::__is_void<_DiffType>::__type>
00061         struct _DiffTraits
00062         { typedef _DiffType __type; };
00063 
00064       template<typename _DiffType>
00065         struct _DiffTraits<_DiffType, std::__true_type>
00066         { typedef std::ptrdiff_t __type; };
00067 
00068       typedef typename _DiffTraits<_ItDiffType>::__type _DiffType;
00069 
00070     public:
00071       typedef std::pair<_DiffType, _Distance_precision> __type;
00072     };
00073 
00074   template<typename _Integral>
00075     struct _Distance_traits<_Integral, std::__true_type>
00076     { typedef std::pair<std::ptrdiff_t, _Distance_precision> __type; };
00077 
00078   /** Determine the distance between two iterators with some known
00079    *    precision.
00080   */
00081   template<typename _Iterator>
00082     inline typename _Distance_traits<_Iterator>::__type
00083     __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
00084                    std::random_access_iterator_tag)
00085     { return std::make_pair(__rhs - __lhs, __dp_exact); }
00086 
00087   template<typename _Iterator>
00088     inline typename _Distance_traits<_Iterator>::__type
00089     __get_distance(const _Iterator& __lhs, const _Iterator& __rhs,
00090                    std::input_iterator_tag)
00091     {
00092       if (__lhs == __rhs)
00093         return std::make_pair(0, __dp_exact);
00094 
00095       return std::make_pair(1, __dp_equality);
00096     }
00097 
00098   template<typename _Iterator>
00099     inline typename _Distance_traits<_Iterator>::__type
00100     __get_distance(const _Iterator& __lhs, const _Iterator& __rhs)
00101     { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); }
00102 
00103   /** We say that integral types for a valid range, and defer to other
00104    *  routines to realize what to do with integral types instead of
00105    *  iterators.
00106   */
00107   template<typename _Integral>
00108     inline bool
00109     __valid_range_aux(const _Integral&, const _Integral&,
00110                       typename _Distance_traits<_Integral>::__type& __dist,
00111                       std::__true_type)
00112     {
00113       __dist = std::make_pair(0, __dp_none);
00114       return true;
00115     }
00116 
00117   /** We have iterators, so figure out what kind of iterators that are
00118    *  to see if we can check the range ahead of time.
00119   */
00120   template<typename _InputIterator>
00121     inline bool
00122     __valid_range_aux(const _InputIterator& __first,
00123                       const _InputIterator& __last,
00124                       typename _Distance_traits<_InputIterator>::__type& __dist,
00125                       std::__false_type)
00126     {
00127       __dist = __get_distance(__first, __last);
00128       switch (__dist.second)
00129         {
00130         case __dp_none:
00131           break;
00132         case __dp_equality:
00133           if (__dist.first == 0)
00134             return true;
00135           break;
00136         case __dp_sign:
00137         case __dp_exact:
00138           return __dist.first >= 0;
00139         }
00140 
00141       return true;
00142     }
00143 
00144   /** Don't know what these iterators are, or if they are even
00145    *  iterators (we may get an integral type for InputIterator), so
00146    *  see if they are integral and pass them on to the next phase
00147    *  otherwise.
00148   */
00149   template<typename _InputIterator>
00150     inline bool
00151     __valid_range(const _InputIterator& __first, const _InputIterator& __last,
00152                   typename _Distance_traits<_InputIterator>::__type& __dist)
00153     {
00154       typedef typename std::__is_integer<_InputIterator>::__type _Integral;
00155       return __valid_range_aux(__first, __last, __dist, _Integral());
00156     }
00157 
00158   template<typename _InputIterator>
00159     inline bool
00160     __valid_range(const _InputIterator& __first, const _InputIterator& __last)
00161     {
00162       typename _Distance_traits<_InputIterator>::__type __dist;
00163       return __valid_range(__first, __last, __dist);
00164     }
00165 
00166 #if __cplusplus < 201103L
00167   // Helper struct to detect random access safe iterators.
00168   template<typename _Iterator>
00169     struct __is_safe_random_iterator
00170     {
00171       enum { __value = 0 };
00172       typedef std::__false_type __type;
00173     };
00174 
00175   template<typename _Iterator>
00176     struct _Siter_base
00177     : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value>
00178     { };
00179 
00180   /** Helper function to extract base iterator of random access safe iterator
00181       in order to reduce performance impact of debug mode.  Limited to random
00182       access iterator because it is the only category for which it is possible
00183       to check for correct iterators order in the __valid_range function
00184       thanks to the < operator.
00185   */
00186   template<typename _Iterator>
00187     inline typename _Siter_base<_Iterator>::iterator_type
00188     __base(_Iterator __it)
00189     { return _Siter_base<_Iterator>::_S_base(__it); }
00190 #else
00191   template<typename _Iterator>
00192     inline _Iterator
00193     __base(_Iterator __it)
00194     { return __it; }
00195 #endif
00196 
00197 #if __cplusplus < 201103L
00198   template<typename _Iterator>
00199     struct _Unsafe_type
00200     { typedef _Iterator _Type; };
00201 #endif
00202 
00203   /* Remove debug mode safe iterator layer, if any. */
00204   template<typename _Iterator>
00205     inline _Iterator
00206     __unsafe(_Iterator __it)
00207     { return __it; }
00208 }
00209 
00210 #endif