iterator.hpp
Go to the documentation of this file.
00001 // (C) Copyright David Abrahams 2002.
00002 // Distributed under the Boost Software License, Version 1.0. (See
00003 // accompanying file LICENSE_1_0.txt or copy at
00004 // http://www.boost.org/LICENSE_1_0.txt)
00005 
00006 // Boost versions of
00007 //
00008 //    std::iterator_traits<>::iterator_category
00009 //    std::iterator_traits<>::difference_type
00010 //    std::distance()
00011 //
00012 // ...for all compilers and iterators
00013 //
00014 // Additionally, if X is a pointer
00015 //    std::iterator_traits<X>::pointer
00016 
00017 // Otherwise, if partial specialization is supported or X is not a pointer
00018 //    std::iterator_traits<X>::value_type
00019 //    std::iterator_traits<X>::pointer
00020 //    std::iterator_traits<X>::reference
00021 //
00022 // See http://www.boost.org for most recent version including documentation.
00023 
00024 // Revision History
00025 // 04 Mar 2001 - More attempted fixes for Intel C++ (David Abrahams)
00026 // 03 Mar 2001 - Put all implementation into namespace
00027 //               boost::detail::iterator_traits_. Some progress made on fixes
00028 //               for Intel compiler. (David Abrahams)
00029 // 02 Mar 2001 - Changed BOOST_MSVC to BOOST_MSVC_STD_ITERATOR in a few
00030 //               places. (Jeremy Siek)
00031 // 19 Feb 2001 - Improved workarounds for stock MSVC6; use yes_type and
00032 //               no_type from type_traits.hpp; stopped trying to remove_cv
00033 //               before detecting is_pointer, in honor of the new type_traits
00034 //               semantics. (David Abrahams)
00035 // 13 Feb 2001 - Make it work with nearly all standard-conforming iterators
00036 //               under raw VC6. The one category remaining which will fail is
00037 //               that of iterators derived from std::iterator but not
00038 //               boost::iterator and which redefine difference_type.
00039 // 11 Feb 2001 - Clean away code which can never be used (David Abrahams)
00040 // 09 Feb 2001 - Always have a definition for each traits member, even if it
00041 //               can't be properly deduced. These will be incomplete types in
00042 //               some cases (undefined<void>), but it helps suppress MSVC errors
00043 //               elsewhere (David Abrahams)
00044 // 07 Feb 2001 - Support for more of the traits members where possible, making
00045 //               this useful as a replacement for std::iterator_traits<T> when
00046 //               used as a default template parameter.
00047 // 06 Feb 2001 - Removed useless #includes of standard library headers
00048 //               (David Abrahams)
00049 
00050 #ifndef ITERATOR_DWA122600_HPP_
00051 # define ITERATOR_DWA122600_HPP_
00052 
00053 # include <boost/config.hpp>
00054 # include <iterator>
00055 
00056 // STLPort 4.0 and betas have a bug when debugging is enabled and there is no
00057 // partial specialization: instead of an iterator_category typedef, the standard
00058 // container iterators have _Iterator_category.
00059 //
00060 // Also, whether debugging is enabled or not, there is a broken specialization
00061 // of std::iterator<output_iterator_tag,void,void,void,void> which has no
00062 // typedefs but iterator_category.
00063 # if defined(__SGI_STL_PORT)
00064 
00065 #  if (__SGI_STL_PORT <= 0x410) && !defined(__STL_CLASS_PARTIAL_SPECIALIZATION) && defined(__STL_DEBUG)
00066 #   define BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
00067 #  endif
00068 
00069 #  define BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
00070 
00071 # endif // STLPort <= 4.1b4 && no partial specialization
00072 
00073 # if !defined(BOOST_NO_STD_ITERATOR_TRAITS)             \
00074   && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
00075   && !defined(BOOST_MSVC_STD_ITERATOR)
00076     
00077 namespace boost { namespace detail {
00078 
00079 // Define a new template so it can be specialized
00080 template <class Iterator>
00081 struct iterator_traits
00082     : std::iterator_traits<Iterator>
00083 {};
00084 using std::distance;
00085 
00086 }} // namespace boost::detail
00087 
00088 # else
00089 
00090 #  if  !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)  \
00091     && !defined(BOOST_MSVC_STD_ITERATOR)
00092 
00093 // This is the case where everything conforms except BOOST_NO_STD_ITERATOR_TRAITS
00094 
00095 namespace boost { namespace detail {
00096 
00097 // Rogue Wave Standard Library fools itself into thinking partial
00098 // specialization is missing on some platforms (e.g. Sun), so fails to
00099 // supply iterator_traits!
00100 template <class Iterator>
00101 struct iterator_traits
00102 {
00103     typedef typename Iterator::value_type value_type;
00104     typedef typename Iterator::reference reference;
00105     typedef typename Iterator::pointer pointer;
00106     typedef typename Iterator::difference_type difference_type;
00107     typedef typename Iterator::iterator_category iterator_category;
00108 };
00109 
00110 template <class T>
00111 struct iterator_traits<T*>
00112 {
00113     typedef T value_type;
00114     typedef T& reference;
00115     typedef T* pointer;
00116     typedef std::ptrdiff_t difference_type;
00117     typedef std::random_access_iterator_tag iterator_category;
00118 };
00119 
00120 template <class T>
00121 struct iterator_traits<T const*>
00122 {
00123     typedef T value_type;
00124     typedef T const& reference;
00125     typedef T const* pointer;
00126     typedef std::ptrdiff_t difference_type;
00127     typedef std::random_access_iterator_tag iterator_category;
00128 };
00129 
00130 }} // namespace boost::detail
00131 
00132 #  else
00133 
00134 # include <boost/type_traits/remove_const.hpp>
00135 # include <boost/type_traits/detail/yes_no_type.hpp>
00136 # include <boost/type_traits/is_pointer.hpp>
00137 
00138 # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
00139 #  include <boost/type_traits/is_same.hpp>
00140 #  include <boost/type_traits/remove_pointer.hpp>
00141 # endif
00142 # ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
00143 #  include <boost/type_traits/is_base_and_derived.hpp>
00144 # endif
00145 
00146 # include <boost/mpl/if.hpp>
00147 # include <boost/mpl/has_xxx.hpp>
00148 # include <cstddef>
00149 
00150 // should be the last #include
00151 # include "boost/type_traits/detail/bool_trait_def.hpp"
00152 
00153 namespace boost { namespace detail {
00154 
00155 BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type)
00156 BOOST_MPL_HAS_XXX_TRAIT_DEF(reference)
00157 BOOST_MPL_HAS_XXX_TRAIT_DEF(pointer)
00158 BOOST_MPL_HAS_XXX_TRAIT_DEF(difference_type)
00159 BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator_category)
00160 
00161 // is_mutable_iterator --
00162 //
00163 //   A metafunction returning true iff T is a mutable iterator type
00164 //   with a nested value_type. Will only work portably with iterators
00165 //   whose operator* returns a reference, but that seems to be OK for
00166 //   the iterators supplied by Dinkumware. Some input iterators may
00167 //   compile-time if they arrive here, and if the compiler is strict
00168 //   about not taking the address of an rvalue.
00169 
00170 // This one detects ordinary mutable iterators - the result of
00171 // operator* is convertible to the value_type.
00172 template <class T>
00173 type_traits::yes_type is_mutable_iterator_helper(T const*, BOOST_DEDUCED_TYPENAME T::value_type*);
00174 
00175 // Since you can't take the address of an rvalue, the guts of
00176 // is_mutable_iterator_impl will fail if we use &*t directly.  This
00177 // makes sure we can still work with non-lvalue iterators.
00178 template <class T> T* mutable_iterator_lvalue_helper(T& x);
00179 int mutable_iterator_lvalue_helper(...);
00180 
00181 
00182 // This one detects output iterators such as ostream_iterator which
00183 // return references to themselves.
00184 template <class T>
00185 type_traits::yes_type is_mutable_iterator_helper(T const*, T const*);
00186 
00187 type_traits::no_type is_mutable_iterator_helper(...);
00188 
00189 template <class T>
00190 struct is_mutable_iterator_impl
00191 {
00192     static T t;
00193     
00194     BOOST_STATIC_CONSTANT(
00195         bool, value = sizeof(
00196             detail::is_mutable_iterator_helper(
00197                 (T*)0
00198               , mutable_iterator_lvalue_helper(*t) // like &*t
00199             ))
00200         == sizeof(type_traits::yes_type)
00201     );
00202 };
00203 
00204 BOOST_TT_AUX_BOOL_TRAIT_DEF1(
00205     is_mutable_iterator,T,::boost::detail::is_mutable_iterator_impl<T>::value)
00206 
00207 
00208 // is_full_iterator_traits --
00209 //
00210 //   A metafunction returning true iff T has all the requisite nested
00211 //   types to satisfy the requirements for a fully-conforming
00212 //   iterator_traits implementation.
00213 template <class T>
00214 struct is_full_iterator_traits_impl
00215 {
00216     enum { value = 
00217            has_value_type<T>::value 
00218            & has_reference<T>::value 
00219            & has_pointer<T>::value 
00220            & has_difference_type<T>::value
00221            & has_iterator_category<T>::value
00222     };
00223 };
00224 
00225 BOOST_TT_AUX_BOOL_TRAIT_DEF1(
00226     is_full_iterator_traits,T,::boost::detail::is_full_iterator_traits_impl<T>::value)
00227 
00228 
00229 #   ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
00230 BOOST_MPL_HAS_XXX_TRAIT_DEF(_Iterator_category)
00231     
00232 // is_stlport_40_debug_iterator --
00233 //
00234 //   A metafunction returning true iff T has all the requisite nested
00235 //   types to satisfy the requirements of an STLPort 4.0 debug iterator
00236 //   iterator_traits implementation.
00237 template <class T>
00238 struct is_stlport_40_debug_iterator_impl
00239 {
00240     enum { value = 
00241            has_value_type<T>::value 
00242            & has_reference<T>::value 
00243            & has_pointer<T>::value 
00244            & has_difference_type<T>::value
00245            & has__Iterator_category<T>::value
00246     };
00247 };
00248 
00249 BOOST_TT_AUX_BOOL_TRAIT_DEF1(
00250     is_stlport_40_debug_iterator,T,::boost::detail::is_stlport_40_debug_iterator_impl<T>::value)
00251 
00252 template <class T>
00253 struct stlport_40_debug_iterator_traits
00254 {
00255     typedef typename T::value_type value_type;
00256     typedef typename T::reference reference;
00257     typedef typename T::pointer pointer;
00258     typedef typename T::difference_type difference_type;
00259     typedef typename T::_Iterator_category iterator_category;
00260 };
00261 #   endif // BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF 
00262 
00263 template <class T> struct pointer_iterator_traits;
00264 
00265 #   ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
00266 template <class T>
00267 struct pointer_iterator_traits<T*>
00268 {
00269     typedef typename remove_const<T>::type value_type;
00270     typedef T* pointer;
00271     typedef T& reference;
00272     typedef std::random_access_iterator_tag iterator_category;
00273     typedef std::ptrdiff_t difference_type;
00274 };
00275 #   else
00276 
00277 // In case of no template partial specialization, and if T is a
00278 // pointer, iterator_traits<T>::value_type can still be computed.  For
00279 // some basic types, remove_pointer is manually defined in
00280 // type_traits/broken_compiler_spec.hpp. For others, do it yourself.
00281 
00282 template<class P> class please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee;
00283 
00284 template<class P>
00285 struct pointer_value_type
00286   : mpl::if_<
00287         is_same<P, typename remove_pointer<P>::type>
00288       , please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee<P>
00289       , typename remove_const<
00290             typename remove_pointer<P>::type
00291         >::type
00292     >
00293 {
00294 };
00295 
00296 
00297 template<class P>
00298 struct pointer_reference
00299   : mpl::if_<
00300         is_same<P, typename remove_pointer<P>::type>
00301       , please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee<P>
00302       , typename remove_pointer<P>::type&
00303     >
00304 {
00305 };
00306 
00307 template <class T>
00308 struct pointer_iterator_traits
00309 {
00310     typedef T pointer;
00311     typedef std::random_access_iterator_tag iterator_category;
00312     typedef std::ptrdiff_t difference_type;
00313 
00314     typedef typename pointer_value_type<T>::type value_type;
00315     typedef typename pointer_reference<T>::type reference;
00316 };
00317 
00318 #   endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
00319 
00320 // We'll sort iterator types into one of these classifications, from which we
00321 // can determine the difference_type, pointer, reference, and value_type
00322 template <class Iterator>
00323 struct standard_iterator_traits
00324 {
00325     typedef typename Iterator::difference_type difference_type;
00326     typedef typename Iterator::value_type value_type;
00327     typedef typename Iterator::pointer pointer;
00328     typedef typename Iterator::reference reference;
00329     typedef typename Iterator::iterator_category iterator_category;
00330 };
00331 
00332 template <class Iterator>
00333 struct msvc_stdlib_mutable_traits
00334     : std::iterator_traits<Iterator>
00335 {
00336     typedef typename std::iterator_traits<Iterator>::distance_type difference_type;
00337     typedef typename std::iterator_traits<Iterator>::value_type* pointer;
00338     typedef typename std::iterator_traits<Iterator>::value_type& reference;
00339 };
00340 
00341 template <class Iterator>
00342 struct msvc_stdlib_const_traits
00343     : std::iterator_traits<Iterator>
00344 {
00345     typedef typename std::iterator_traits<Iterator>::distance_type difference_type;
00346     typedef const typename std::iterator_traits<Iterator>::value_type* pointer;
00347     typedef const typename std::iterator_traits<Iterator>::value_type& reference;
00348 };
00349 
00350 #   ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
00351 template <class Iterator>
00352 struct is_bad_output_iterator
00353     : is_base_and_derived<
00354         std::iterator<std::output_iterator_tag,void,void,void,void>
00355         , Iterator>
00356 {
00357 };
00358 
00359 struct bad_output_iterator_traits
00360 {
00361     typedef void value_type;
00362     typedef void difference_type;
00363     typedef std::output_iterator_tag iterator_category;
00364     typedef void pointer;
00365     typedef void reference;
00366 };
00367 #   endif
00368 
00369 // If we're looking at an MSVC6 (old Dinkumware) ``standard''
00370 // iterator, this will generate an appropriate traits class. 
00371 template <class Iterator>
00372 struct msvc_stdlib_iterator_traits
00373     : mpl::if_<
00374        is_mutable_iterator<Iterator>
00375        , msvc_stdlib_mutable_traits<Iterator>
00376        , msvc_stdlib_const_traits<Iterator>
00377       >::type
00378 {};
00379 
00380 template <class Iterator>
00381 struct non_pointer_iterator_traits
00382     : mpl::if_<
00383         // if the iterator contains all the right nested types...
00384         is_full_iterator_traits<Iterator>
00385         // Use a standard iterator_traits implementation
00386         , standard_iterator_traits<Iterator>
00387 #   ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
00388         // Check for STLPort 4.0 broken _Iterator_category type
00389         , mpl::if_<
00390              is_stlport_40_debug_iterator<Iterator>
00391              , stlport_40_debug_iterator_traits<Iterator>
00392 #   endif
00393         // Otherwise, assume it's a Dinkum iterator
00394         , msvc_stdlib_iterator_traits<Iterator>
00395 #   ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
00396         >::type
00397 #   endif 
00398     >::type
00399 {
00400 };
00401 
00402 template <class Iterator>
00403 struct iterator_traits_aux
00404     : mpl::if_<
00405         is_pointer<Iterator>
00406         , pointer_iterator_traits<Iterator>
00407         , non_pointer_iterator_traits<Iterator>
00408     >::type
00409 {
00410 };
00411 
00412 template <class Iterator>
00413 struct iterator_traits
00414 {
00415     // Explicit forwarding from base class needed to keep MSVC6 happy
00416     // under some circumstances.
00417  private:
00418 #   ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
00419     typedef 
00420     typename mpl::if_<
00421         is_bad_output_iterator<Iterator>
00422         , bad_output_iterator_traits
00423         , iterator_traits_aux<Iterator>
00424     >::type base;
00425 #   else
00426     typedef iterator_traits_aux<Iterator> base;
00427 #   endif
00428  public:
00429     typedef typename base::value_type value_type;
00430     typedef typename base::pointer pointer;
00431     typedef typename base::reference reference;
00432     typedef typename base::difference_type difference_type;
00433     typedef typename base::iterator_category iterator_category;
00434 };
00435 
00436 // This specialization cuts off ETI (Early Template Instantiation) for MSVC.
00437 template <> struct iterator_traits<int>
00438 {
00439     typedef int value_type;
00440     typedef int pointer;
00441     typedef int reference;
00442     typedef int difference_type;
00443     typedef int iterator_category;
00444 };
00445 
00446 }} // namespace boost::detail
00447 
00448 #  endif // workarounds
00449 
00450 namespace boost { namespace detail {
00451 
00452 namespace iterator_traits_
00453 {
00454   template <class Iterator, class Difference>
00455   struct distance_select
00456   {
00457       static Difference execute(Iterator i1, const Iterator i2, ...)
00458       {
00459           Difference result = 0;
00460           while (i1 != i2)
00461           {
00462               ++i1;
00463               ++result;
00464           }
00465           return result;
00466       }
00467 
00468       static Difference execute(Iterator i1, const Iterator i2, std::random_access_iterator_tag*)
00469       {
00470           return i2 - i1;
00471       }
00472   };
00473 } // namespace boost::detail::iterator_traits_
00474 
00475 template <class Iterator>
00476 inline typename iterator_traits<Iterator>::difference_type
00477 distance(Iterator first, Iterator last)
00478 {
00479     typedef typename iterator_traits<Iterator>::difference_type diff_t;
00480     typedef typename ::boost::detail::iterator_traits<Iterator>::iterator_category iterator_category;
00481     
00482     return iterator_traits_::distance_select<Iterator,diff_t>::execute(
00483         first, last, (iterator_category*)0);
00484 }
00485 
00486 }}
00487 
00488 # endif
00489 
00490 
00491 # undef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
00492 # undef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
00493 
00494 #endif // ITERATOR_DWA122600_HPP_


appl
Author(s): petercai
autogenerated on Tue Jan 7 2014 11:02:29