]> git.lyx.org Git - lyx.git/blobdiff - boost/boost/detail/iterator.hpp
Add forgotten test to distribution
[lyx.git] / boost / boost / detail / iterator.hpp
index 9833146f47162f5417d716ea587a4ea81e557d83..5bb9c6269cf579af78260465714794a6d5564e31 100644 (file)
@@ -1,8 +1,7 @@
-// (C) Copyright David Abrahams 2001. Permission to copy, use, modify,
-// sell and distribute this software is granted provided this
-// copyright notice appears in all copies. This software is provided
-// "as is" without express or implied warranty, and with no claim as
-// to its suitability for any purpose.
+// (C) Copyright David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
 
 // Boost versions of
 //
 //    std::iterator_traits<X>::pointer
 //    std::iterator_traits<X>::reference
 //
-// CAVEAT: When using the VC6 standard library, an iterator derived from
-// std::iterator but not boost::iterator or from one supplied by the standard
-// will always have pointer == const value_type* and reference == const
-// value_type&, whether that's correct or not.
-
 // See http://www.boost.org for most recent version including documentation.
 
 // Revision History
 # define ITERATOR_DWA122600_HPP_
 
 # include <boost/config.hpp>
-# include <boost/type_traits.hpp>
-# include <boost/iterator.hpp>
 # include <iterator>
-# include <cstddef>
-
-# if defined(BOOST_MSVC_STD_ITERATOR) && !defined(__SGI_STL_PORT)
-#  include <xtree>
-#  include <deque>
-#  include <list>
-# endif
-
 
 // STLPort 4.0 and betas have a bug when debugging is enabled and there is no
 // partial specialization: instead of an iterator_category typedef, the standard
@@ -76,9 +60,9 @@
 // Also, whether debugging is enabled or not, there is a broken specialization
 // of std::iterator<output_iterator_tag,void,void,void,void> which has no
 // typedefs but iterator_category.
-# if defined(__SGI_STL_PORT) && (__SGI_STL_PORT <= 0x410) && !defined(__STL_CLASS_PARTIAL_SPECIALIZATION)
+# if defined(__SGI_STL_PORT)
 
-#  ifdef __STL_DEBUG
+#  if (__SGI_STL_PORT <= 0x410) && !defined(__STL_CLASS_PARTIAL_SPECIALIZATION) && defined(__STL_DEBUG)
 #   define BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
 #  endif
 
 
 # endif // STLPort <= 4.1b4 && no partial specialization
 
+# if !defined(BOOST_NO_STD_ITERATOR_TRAITS)             \
+  && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+  && !defined(BOOST_MSVC_STD_ITERATOR)
+    
 namespace boost { namespace detail {
-# if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR)
-using std::iterator_traits;
+
+// Define a new template so it can be specialized
+template <class Iterator>
+struct iterator_traits
+    : std::iterator_traits<Iterator>
+{};
 using std::distance;
+
+}} // namespace boost::detail
+
 # else
 
-namespace iterator_traits_ {
+#  if  !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)  \
+    && !defined(BOOST_MSVC_STD_ITERATOR)
 
-// Workarounds for less-capable implementations
-template <bool is_ptr> struct iterator_traits_select;
+// This is the case where everything conforms except BOOST_NO_STD_ITERATOR_TRAITS
 
-template <class T> struct undefined;
-template <> struct iterator_traits_select<true>
+namespace boost { namespace detail {
+
+// Rogue Wave Standard Library fools itself into thinking partial
+// specialization is missing on some platforms (e.g. Sun), so fails to
+// supply iterator_traits!
+template <class Iterator>
+struct iterator_traits
 {
-    template <class Ptr>
-    struct traits
-    {
-        typedef std::ptrdiff_t difference_type;
-        typedef std::random_access_iterator_tag iterator_category;
-        typedef Ptr pointer;
-#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
-// Keeps MSVC happy under certain circumstances. It seems class template default
-// arguments are partly instantiated even when not used when the class template
-// is the return type of a function template.
-        typedef undefined<void> value_type;
-        typedef undefined<void> reference;
-#endif
+    typedef typename Iterator::value_type value_type;
+    typedef typename Iterator::reference reference;
+    typedef typename Iterator::pointer pointer;
+    typedef typename Iterator::difference_type difference_type;
+    typedef typename Iterator::iterator_category iterator_category;
+};
+
+template <class T>
+struct iterator_traits<T*>
+{
+    typedef T value_type;
+    typedef T& reference;
+    typedef T* pointer;
+    typedef std::ptrdiff_t difference_type;
+    typedef std::random_access_iterator_tag iterator_category;
+};
+
+template <class T>
+struct iterator_traits<T const*>
+{
+    typedef T value_type;
+    typedef T const& reference;
+    typedef T const* pointer;
+    typedef std::ptrdiff_t difference_type;
+    typedef std::random_access_iterator_tag iterator_category;
+};
+
+}} // namespace boost::detail
+
+#  else
+
+# include <boost/type_traits/remove_const.hpp>
+# include <boost/type_traits/detail/yes_no_type.hpp>
+# include <boost/type_traits/is_pointer.hpp>
+
+# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+#  include <boost/type_traits/is_same.hpp>
+#  include <boost/type_traits/remove_pointer.hpp>
+# endif
+# ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
+#  include <boost/type_traits/is_base_and_derived.hpp>
+# endif
+
+# include <boost/mpl/if.hpp>
+# include <boost/mpl/has_xxx.hpp>
+# include <cstddef>
+
+// should be the last #include
+# include "boost/type_traits/detail/bool_trait_def.hpp"
+
+namespace boost { namespace detail {
+
+BOOST_MPL_HAS_XXX_TRAIT_DEF(value_type)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(reference)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(pointer)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(difference_type)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator_category)
+
+// is_mutable_iterator --
+//
+//   A metafunction returning true iff T is a mutable iterator type
+//   with a nested value_type. Will only work portably with iterators
+//   whose operator* returns a reference, but that seems to be OK for
+//   the iterators supplied by Dinkumware. Some input iterators may
+//   compile-time if they arrive here, and if the compiler is strict
+//   about not taking the address of an rvalue.
+
+// This one detects ordinary mutable iterators - the result of
+// operator* is convertible to the value_type.
+template <class T>
+type_traits::yes_type is_mutable_iterator_helper(T const*, BOOST_DEDUCED_TYPENAME T::value_type*);
+
+// Since you can't take the address of an rvalue, the guts of
+// is_mutable_iterator_impl will fail if we use &*t directly.  This
+// makes sure we can still work with non-lvalue iterators.
+template <class T> T* mutable_iterator_lvalue_helper(T& x);
+int mutable_iterator_lvalue_helper(...);
+
+
+// This one detects output iterators such as ostream_iterator which
+// return references to themselves.
+template <class T>
+type_traits::yes_type is_mutable_iterator_helper(T const*, T const*);
+
+type_traits::no_type is_mutable_iterator_helper(...);
+
+template <class T>
+struct is_mutable_iterator_impl
+{
+    static T t;
+    
+    BOOST_STATIC_CONSTANT(
+        bool, value = sizeof(
+            detail::is_mutable_iterator_helper(
+                (T*)0
+              , mutable_iterator_lvalue_helper(*t) // like &*t
+            ))
+        == sizeof(type_traits::yes_type)
+    );
+};
+
+BOOST_TT_AUX_BOOL_TRAIT_DEF1(
+    is_mutable_iterator,T,::boost::detail::is_mutable_iterator_impl<T>::value)
+
+
+// is_full_iterator_traits --
+//
+//   A metafunction returning true iff T has all the requisite nested
+//   types to satisfy the requirements for a fully-conforming
+//   iterator_traits implementation.
+template <class T>
+struct is_full_iterator_traits_impl
+{
+    enum { value = 
+           has_value_type<T>::value 
+           & has_reference<T>::value 
+           & has_pointer<T>::value 
+           & has_difference_type<T>::value
+           & has_iterator_category<T>::value
     };
 };
 
+BOOST_TT_AUX_BOOL_TRAIT_DEF1(
+    is_full_iterator_traits,T,::boost::detail::is_full_iterator_traits_impl<T>::value)
 
-typedef char yes_type;
-typedef double no_type;
 
-# ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
+#   ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
+BOOST_MPL_HAS_XXX_TRAIT_DEF(_Iterator_category)
+    
+// is_stlport_40_debug_iterator --
+//
+//   A metafunction returning true iff T has all the requisite nested
+//   types to satisfy the requirements of an STLPort 4.0 debug iterator
+//   iterator_traits implementation.
+template <class T>
+struct is_stlport_40_debug_iterator_impl
+{
+    enum { value = 
+           has_value_type<T>::value 
+           & has_reference<T>::value 
+           & has_pointer<T>::value 
+           & has_difference_type<T>::value
+           & has__Iterator_category<T>::value
+    };
+};
 
-no_type bad_category_helper(...);
-template <class C, class T> yes_type bad_category_helper(std::_DBG_iter<C,T>*);
+BOOST_TT_AUX_BOOL_TRAIT_DEF1(
+    is_stlport_40_debug_iterator,T,::boost::detail::is_stlport_40_debug_iterator_impl<T>::value)
 
-template <bool has_bad_category_typedef> struct bad_category_select;
-template <>
-struct bad_category_select<true>
+template <class T>
+struct stlport_40_debug_iterator_traits
 {
-    template <class Iterator>
-    struct category { typedef typename Iterator::_Iterator_category type; };
+    typedef typename T::value_type value_type;
+    typedef typename T::reference reference;
+    typedef typename T::pointer pointer;
+    typedef typename T::difference_type difference_type;
+    typedef typename T::_Iterator_category iterator_category;
 };
-template <>
-struct bad_category_select<false>
+#   endif // BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF 
+
+template <class T> struct pointer_iterator_traits;
+
+#   ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+template <class T>
+struct pointer_iterator_traits<T*>
 {
-    template <class Iterator>
-    struct category { typedef typename Iterator::iterator_category type; };
+    typedef typename remove_const<T>::type value_type;
+    typedef T* pointer;
+    typedef T& reference;
+    typedef std::random_access_iterator_tag iterator_category;
+    typedef std::ptrdiff_t difference_type;
 };
+#   else
 
-template <class Iterator>
-struct iterator_category_select
+// In case of no template partial specialization, and if T is a
+// pointer, iterator_traits<T>::value_type can still be computed.  For
+// some basic types, remove_pointer is manually defined in
+// type_traits/broken_compiler_spec.hpp. For others, do it yourself.
+
+template<class P> class please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee;
+
+template<class P>
+struct pointer_value_type
+  : mpl::if_<
+        is_same<P, typename remove_pointer<P>::type>
+      , please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee<P>
+      , typename remove_const<
+            typename remove_pointer<P>::type
+        >::type
+    >
 {
- private:
-    static Iterator p;
-    enum { has_bad_category
-           = sizeof(bad_category_helper(&p)) == sizeof(yes_type) };
-    typedef bad_category_select<has_bad_category> category_select;
- public:
-    typedef typename category_select::template category<Iterator>::type type;
 };
 
-# endif
 
-# ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
-template <bool is_bad_output_iterator> struct bad_output_iterator_select;
-template <>
-struct bad_output_iterator_select<true>
+template<class P>
+struct pointer_reference
+  : mpl::if_<
+        is_same<P, typename remove_pointer<P>::type>
+      , please_invoke_BOOST_TT_BROKEN_COMPILER_SPEC_on_cv_unqualified_pointee<P>
+      , typename remove_pointer<P>::type&
+    >
 {
-    template <class Iterator>
-    struct non_category_traits {
-        typedef void value_type;
-        typedef void difference_type;
-        typedef void pointer;
-        typedef void reference;
-    };
 };
-template <>
-struct bad_output_iterator_select<false>
+
+template <class T>
+struct pointer_iterator_traits
 {
-    template <class Iterator>
-    struct non_category_traits {
-        typedef typename Iterator::value_type value_type;
-        typedef typename Iterator::difference_type difference_type;
-        typedef typename Iterator::pointer pointer;
-        typedef typename Iterator::reference reference;
-    };
+    typedef T pointer;
+    typedef std::random_access_iterator_tag iterator_category;
+    typedef std::ptrdiff_t difference_type;
+
+    typedef typename pointer_value_type<T>::type value_type;
+    typedef typename pointer_reference<T>::type reference;
 };
-# endif
 
-# if defined(BOOST_MSVC_STD_ITERATOR) && !defined(__SGI_STL_PORT)
+#   endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 
 // We'll sort iterator types into one of these classifications, from which we
 // can determine the difference_type, pointer, reference, and value_type
-enum {
-    not_msvc_stdlib_iterator,
-    msvc_stdlib_const_iterator,
-    msvc_stdlib_mutable_iterator,
-    msvc_stdlib_ostream_iterator
+template <class Iterator>
+struct standard_iterator_traits
+{
+    typedef typename Iterator::difference_type difference_type;
+    typedef typename Iterator::value_type value_type;
+    typedef typename Iterator::pointer pointer;
+    typedef typename Iterator::reference reference;
+    typedef typename Iterator::iterator_category iterator_category;
 };
-       
-template <unsigned> struct msvc_traits_select;
 
-template <> struct msvc_traits_select<not_msvc_stdlib_iterator>
+template <class Iterator>
+struct msvc_stdlib_mutable_traits
+    : std::iterator_traits<Iterator>
 {
-    template <class Iterator>
-    struct traits_     // calling this "traits" will confuse VC.
-    {
-        typedef typename Iterator::difference_type difference_type;
-        typedef typename Iterator::value_type value_type;
-        typedef typename Iterator::pointer pointer;
-        typedef typename Iterator::reference reference;
-    };
+    typedef typename std::iterator_traits<Iterator>::distance_type difference_type;
+    typedef typename std::iterator_traits<Iterator>::value_type* pointer;
+    typedef typename std::iterator_traits<Iterator>::value_type& reference;
 };
 
-template <> struct msvc_traits_select<msvc_stdlib_mutable_iterator>
+template <class Iterator>
+struct msvc_stdlib_const_traits
+    : std::iterator_traits<Iterator>
 {
-    template <class Iterator>
-    struct traits_
-    {
-        typedef typename Iterator::distance_type difference_type;
-        typedef typename Iterator::value_type value_type;
-        typedef value_type* pointer;
-        typedef value_type& reference;
-    };
+    typedef typename std::iterator_traits<Iterator>::distance_type difference_type;
+    typedef const typename std::iterator_traits<Iterator>::value_type* pointer;
+    typedef const typename std::iterator_traits<Iterator>::value_type& reference;
 };
 
-template <> struct msvc_traits_select<msvc_stdlib_const_iterator>
+#   ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
+template <class Iterator>
+struct is_bad_output_iterator
+    : is_base_and_derived<
+        std::iterator<std::output_iterator_tag,void,void,void,void>
+        , Iterator>
 {
-    template <class Iterator>
-    struct traits_
-    {
-        typedef typename Iterator::distance_type difference_type;
-        typedef typename Iterator::value_type value_type;
-        typedef const value_type* pointer;
-        typedef const value_type& reference;
-    };
 };
 
-template <> struct msvc_traits_select<msvc_stdlib_ostream_iterator>
+struct bad_output_iterator_traits
 {
-    template <class Iterator>
-    struct traits_
-    {
-        typedef typename Iterator::distance_type difference_type;
-        typedef typename Iterator::value_type value_type;
-        typedef void pointer;
-        typedef void reference;
-    };
+    typedef void value_type;
+    typedef void difference_type;
+    typedef std::output_iterator_tag iterator_category;
+    typedef void pointer;
+    typedef void reference;
 };
+#   endif
 
-// These functions allow us to detect which classification a given iterator type
-// falls into.
-
-// Is the iterator derived from std::iterator?
-no_type is_std_iterator_helper(...);
-template <class V, class D, class C>
-yes_type is_std_iterator_helper(const volatile std::iterator<V,D,C>*);
-
-// Is the iterator derived from boost::iterator?
-template <class C, class T, class D, class P, class R>
-yes_type is_boost_iterator_helper(const volatile boost::iterator<C,T,D,P,R>*);
-no_type is_boost_iterator_helper(...);
-
-// Is the iterator one of the known mutable container iterators?
-template<class K, class Ty, class Kfn, class Pr, class A>
-yes_type is_mutable_iterator_helper(const volatile typename std::_Tree<K,Ty,Kfn,Pr,A>::iterator*);
-template<class Ty, class A>
-yes_type is_mutable_iterator_helper(const volatile typename std::list<Ty,A>::iterator*);
-template<class Ty, class A>
-yes_type is_mutable_iterator_helper(const volatile typename std::deque<Ty,A>::iterator*);
-no_type is_mutable_iterator_helper(...);
-
-// Is the iterator an ostream_iterator?
-template<class T, class CharT, class Traits>
-yes_type is_ostream_iterator_helper(const volatile std::ostream_iterator<T,CharT,Traits>*);
-no_type is_ostream_iterator_helper(...);
+// If we're looking at an MSVC6 (old Dinkumware) ``standard''
+// iterator, this will generate an appropriate traits class. 
+template <class Iterator>
+struct msvc_stdlib_iterator_traits
+    : mpl::if_<
+       is_mutable_iterator<Iterator>
+       , msvc_stdlib_mutable_traits<Iterator>
+       , msvc_stdlib_const_traits<Iterator>
+      >::type
+{};
 
-template <class T>
-struct msvc_iterator_classification {
-    BOOST_STATIC_CONSTANT(unsigned,
-        value = (sizeof(is_ostream_iterator_helper((T*)0)) == sizeof(yes_type))
-          ? msvc_stdlib_ostream_iterator
-        : (sizeof(is_mutable_iterator_helper((T*)0)) == sizeof(yes_type))
-          ? msvc_stdlib_mutable_iterator
-        : (sizeof(is_std_iterator_helper((T*)0)) == sizeof(yes_type)
-           && sizeof(is_boost_iterator_helper((T*)0)) == sizeof(no_type))
-        ? msvc_stdlib_const_iterator
-        : not_msvc_stdlib_iterator
-        );
+template <class Iterator>
+struct non_pointer_iterator_traits
+    : mpl::if_<
+        // if the iterator contains all the right nested types...
+        is_full_iterator_traits<Iterator>
+        // Use a standard iterator_traits implementation
+        , standard_iterator_traits<Iterator>
+#   ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
+        // Check for STLPort 4.0 broken _Iterator_category type
+        , mpl::if_<
+             is_stlport_40_debug_iterator<Iterator>
+             , stlport_40_debug_iterator_traits<Iterator>
+#   endif
+        // Otherwise, assume it's a Dinkum iterator
+        , msvc_stdlib_iterator_traits<Iterator>
+#   ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
+        >::type
+#   endif 
+    >::type
+{
 };
-# endif
 
-template <> struct iterator_traits_select<false>
+template <class Iterator>
+struct iterator_traits_aux
+    : mpl::if_<
+        is_pointer<Iterator>
+        , pointer_iterator_traits<Iterator>
+        , non_pointer_iterator_traits<Iterator>
+    >::type
 {
-    template <class Iterator>
-    struct traits
-    {
-#   if defined(BOOST_MSVC_STD_ITERATOR) && !defined(__SGI_STL_PORT)
-        typedef msvc_traits_select<(
-            msvc_iterator_classification<Iterator>::value
-        )>::template traits_<Iterator> inner_traits;
-        
-        typedef typename inner_traits::difference_type difference_type;
-        typedef typename inner_traits::value_type value_type;
-        typedef typename inner_traits::pointer pointer;
-        typedef typename inner_traits::reference reference;
-#   elif !defined(BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION)
-        typedef typename Iterator::difference_type difference_type;
-        typedef typename Iterator::value_type value_type;
-        typedef typename Iterator::pointer pointer;
-        typedef typename Iterator::reference reference;
-#   else
-        typedef bad_output_iterator_select<
-          is_convertible<const volatile Iterator*,
-            const volatile std::iterator<std::output_iterator_tag,void,void,void,void>*
-          >::value> non_category_traits_select;
-        typedef non_category_traits_select::template non_category_traits<Iterator> non_category_traits;
-     public:
-        typedef typename non_category_traits::value_type value_type;
-        typedef typename non_category_traits::difference_type difference_type;
-        typedef typename non_category_traits::pointer pointer;
-        typedef typename non_category_traits::reference reference;
-#   endif
-        
-#   if !defined(BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF)
-        typedef typename Iterator::iterator_category iterator_category;
-#   else
-        typedef typename iterator_category_select<Iterator>::type iterator_category;
-#   endif
-    };
 };
 
-} // namespace boost::detail::iterator_traits_
-
 template <class Iterator>
 struct iterator_traits
-    : iterator_traits_::iterator_traits_select<is_pointer<Iterator>::value>::template traits<Iterator>
 {
+    // Explicit forwarding from base class needed to keep MSVC6 happy
+    // under some circumstances.
  private:
-    typedef typename iterator_traits_::iterator_traits_select<
-        is_pointer<remove_cv<Iterator>::type>::value>::template traits<Iterator> traits;
+#   ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION
+    typedef 
+    typename mpl::if_<
+        is_bad_output_iterator<Iterator>
+        , bad_output_iterator_traits
+        , iterator_traits_aux<Iterator>
+    >::type base;
+#   else
+    typedef iterator_traits_aux<Iterator> base;
+#   endif
  public:
-    // Why do I need to define these typedefs? It keeps MSVC happy somehow.
-    // Why don't I need to define the other typedefs? Who knows?!?
-    typedef typename traits::difference_type difference_type;
-    typedef typename traits::iterator_category iterator_category;
+    typedef typename base::value_type value_type;
+    typedef typename base::pointer pointer;
+    typedef typename base::reference reference;
+    typedef typename base::difference_type difference_type;
+    typedef typename base::iterator_category iterator_category;
 };
 
-namespace iterator_traits_ {
-
-template <class Category>
-struct distance_select {
-    template <class Iterator>
-    static typename ::boost::detail::iterator_traits<Iterator>::difference_type
-    distance(Iterator i1, const Iterator i2)
-    {
-        typename ::boost::detail::iterator_traits<Iterator>::difference_type result = 0;
-        while (i1 != i2)
-        {
-            ++i1;
-            ++result;
-        }
-        return result;
-    }
+// This specialization cuts off ETI (Early Template Instantiation) for MSVC.
+template <> struct iterator_traits<int>
+{
+    typedef int value_type;
+    typedef int pointer;
+    typedef int reference;
+    typedef int difference_type;
+    typedef int iterator_category;
 };
 
-template <>
-struct distance_select<std::random_access_iterator_tag> {
-    template <class Iterator>
-    static typename ::boost::detail::iterator_traits<Iterator>::difference_type
-    distance(const Iterator i1, const Iterator i2)
-    {
-        return i2 - i1;
-    }
-};
+}} // namespace boost::detail
+
+#  endif // workarounds
 
+namespace boost { namespace detail {
+
+namespace iterator_traits_
+{
+  template <class Iterator, class Difference>
+  struct distance_select
+  {
+      static Difference execute(Iterator i1, const Iterator i2, ...)
+      {
+          Difference result = 0;
+          while (i1 != i2)
+          {
+              ++i1;
+              ++result;
+          }
+          return result;
+      }
+
+      static Difference execute(Iterator i1, const Iterator i2, std::random_access_iterator_tag*)
+      {
+          return i2 - i1;
+      }
+  };
 } // namespace boost::detail::iterator_traits_
 
 template <class Iterator>
-inline typename ::boost::detail::iterator_traits<Iterator>::difference_type
-distance(const Iterator& first, const Iterator& last)
+inline typename iterator_traits<Iterator>::difference_type
+distance(Iterator first, Iterator last)
 {
+    typedef typename iterator_traits<Iterator>::difference_type diff_t;
     typedef typename ::boost::detail::iterator_traits<Iterator>::iterator_category iterator_category;
-    return iterator_traits_::distance_select<iterator_category>::distance(first, last);
+    
+    return iterator_traits_::distance_select<Iterator,diff_t>::execute(
+        first, last, (iterator_category*)0);
 }
-# endif // workarounds
 
-}} // namespace boost::detail
+}}
+
+# endif
+
 
 # undef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF
 # undef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION