From 1f335d30ba8cc3da5f9fb304a912075663e3e614 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Fri, 8 Nov 2002 06:57:31 +0000 Subject: [PATCH] Cleanups on boost::iterator_traits<> Broke MSVC though :( [SVN r16157] --- include/boost/detail/iterator.hpp | 452 ++++++++++++++---------------- 1 file changed, 209 insertions(+), 243 deletions(-) diff --git a/include/boost/detail/iterator.hpp b/include/boost/detail/iterator.hpp index 9833146..83e138a 100644 --- a/include/boost/detail/iterator.hpp +++ b/include/boost/detail/iterator.hpp @@ -1,4 +1,4 @@ -// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, +// (C) Copyright David Abrahams 2002. 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 @@ -20,11 +20,6 @@ // std::iterator_traits::pointer // std::iterator_traits::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 @@ -57,17 +52,17 @@ # define ITERATOR_DWA122600_HPP_ # include -# include -# include +# include +# include +# include +# include +# include +# include # include # include -# if defined(BOOST_MSVC_STD_ITERATOR) && !defined(__SGI_STL_PORT) -# include -# include -# include -# endif - +// should be the last #include +#include "boost/type_traits/detail/bool_trait_def.hpp" // 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 +71,9 @@ // Also, whether debugging is enabled or not, there is a broken specialization // of std::iterator 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 @@ -87,293 +82,264 @@ # endif // STLPort <= 4.1b4 && no partial specialization 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; using std::distance; # else -namespace iterator_traits_ { +// is_mutable_iterator -- +// +// A metafunction returning true iff T is a mutable iterator +// type with a nested value_type. -// Workarounds for less-capable implementations -template struct iterator_traits_select; +// This one detects ordinary mutable iterators - the result of +// operator* is convertible to the value_type. +template +type_traits::yes_type is_mutable_iterator_helper(T const*, BOOST_DEDUCED_TYPENAME T::value_type*); -template struct undefined; -template <> struct iterator_traits_select +// This one detects output iterators such as ostream_iterator which +// return references to themselves. +template +type_traits::yes_type is_mutable_iterator_helper(T const*, T const*); + +type_traits::no_type is_mutable_iterator_helper(...); + +template +struct is_mutable_iterator_impl { - template - 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 value_type; - typedef undefined reference; -#endif - }; + static T t; + + BOOST_STATIC_CONSTANT(bool, value = sizeof( + detail::is_mutable_iterator_helper((T*)0, &*t)) + == sizeof(type_traits::yes_type) + ); }; +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_mutable_iterator,T,::boost::detail::is_mutable_iterator_impl::value) -typedef char yes_type; -typedef double no_type; -# ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF +// 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 +type_traits::yes_type is_full_iterator_traits_helper( + T const volatile* + , BOOST_DEDUCED_TYPENAME T::value_type* = 0 + , BOOST_DEDUCED_TYPENAME T::reference (*)() = 0 + , BOOST_DEDUCED_TYPENAME T::pointer* = 0 + , BOOST_DEDUCED_TYPENAME T::difference_type* = 0 + , BOOST_DEDUCED_TYPENAME T::iterator_category* = 0 + ); -no_type bad_category_helper(...); -template yes_type bad_category_helper(std::_DBG_iter*); +type_traits::no_type is_full_iterator_traits_helper(...); -template struct bad_category_select; -template <> -struct bad_category_select +template +struct is_full_iterator_traits_impl { - template - struct category { typedef typename Iterator::_Iterator_category type; }; -}; -template <> -struct bad_category_select -{ - template - struct category { typedef typename Iterator::iterator_category type; }; + enum { value = sizeof( + is_full_iterator_traits_helper((T*)0)) == sizeof(type_traits::yes_type) }; }; -template -struct iterator_category_select +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_full_iterator_traits,T,::boost::detail::is_full_iterator_traits_impl::value) + + +# ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF +// 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 +type_traits::yes_type is_stlport_40_debug_iterator_helper( + T const volatile* + , BOOST_DEDUCED_TYPENAME T::value_type* = 0 + , BOOST_DEDUCED_TYPENAME T::reference (*)() = 0 + , BOOST_DEDUCED_TYPENAME T::pointer* = 0 + , BOOST_DEDUCED_TYPENAME T::difference_type* = 0 + , BOOST_DEDUCED_TYPENAME T::_Iterator_category* = 0 + ); + +type_traits::no_type is_stlport_40_debug_iterator_helper(...); + +template +struct is_stlport_40_debug_iterator_impl { - private: - static Iterator p; - enum { has_bad_category - = sizeof(bad_category_helper(&p)) == sizeof(yes_type) }; - typedef bad_category_select category_select; - public: - typedef typename category_select::template category::type type; + enum { value = sizeof( + is_stlport_40_debug_iterator_helper((T*)0)) == sizeof(type_traits::yes_type) }; }; -# endif +BOOST_TT_AUX_BOOL_TRAIT_DEF1( + is_stlport_40_debug_iterator,T,::boost::detail::is_stlport_40_debug_iterator_impl::value) -# ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION -template struct bad_output_iterator_select; -template <> -struct bad_output_iterator_select +template +struct stlport_40_debug_iterator_traits { - template - struct non_category_traits { - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - }; + 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_output_iterator_select +# endif // BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF + +template +struct pointer_iterator_traits { - template - 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; +}; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct pointer_iterator_traits +{ + typedef remove_const::type value_type; + typedef T* pointer; + typedef T& reference; + typedef std::random_access_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; }; # endif -# if defined(BOOST_MSVC_STD_ITERATOR) && !defined(__SGI_STL_PORT) - // 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 struct msvc_traits_select; - -template <> struct msvc_traits_select +template +struct standard_iterator_traits { - template - 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 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 <> struct msvc_traits_select +template +struct msvc_stdlib_mutable_traits + : std::iterator_traits { - template - 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::distance_type difference_type; + typedef value_type* pointer; + typedef value_type& reference; }; -template <> struct msvc_traits_select +template +struct msvc_stdlib_const_traits + : std::iterator_traits { - template - 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; - }; + typedef typename std::iterator_traits::distance_type difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; }; -template <> struct msvc_traits_select +# ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION +template +struct is_bad_output_iterator + : is_base_and_derived< + std::iterator + , Iterator> { - template - struct traits_ - { - typedef typename Iterator::distance_type difference_type; - typedef typename Iterator::value_type value_type; - typedef void pointer; - typedef void reference; - }; }; -// 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 -yes_type is_std_iterator_helper(const volatile std::iterator*); - -// Is the iterator derived from boost::iterator? -template -yes_type is_boost_iterator_helper(const volatile boost::iterator*); -no_type is_boost_iterator_helper(...); - -// Is the iterator one of the known mutable container iterators? -template -yes_type is_mutable_iterator_helper(const volatile typename std::_Tree::iterator*); -template -yes_type is_mutable_iterator_helper(const volatile typename std::list::iterator*); -template -yes_type is_mutable_iterator_helper(const volatile typename std::deque::iterator*); -no_type is_mutable_iterator_helper(...); - -// Is the iterator an ostream_iterator? -template -yes_type is_ostream_iterator_helper(const volatile std::ostream_iterator*); -no_type is_ostream_iterator_helper(...); - -template -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 - ); +struct bad_output_iterator_traits +{ + typedef void value_type; + typedef void difference_type; + typedef std::output_iterator_tag iterator_category; + typedef void pointer; + typedef void reference; }; # endif -template <> struct iterator_traits_select +template +struct non_pointer_iterator_traits + : mpl::if_< + is_full_iterator_traits + , standard_iterator_traits +# ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF + , mpl::if_< + is_stlport_40_debug_iterator + , stlport_40_debug_iterator_traits +# endif + , mpl::if_< + is_mutable_iterator + , msvc_stdlib_mutable_traits + , msvc_stdlib_const_traits + >::type +# ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF + >::type +# endif + >::type { - template - struct traits - { -# if defined(BOOST_MSVC_STD_ITERATOR) && !defined(__SGI_STL_PORT) - typedef msvc_traits_select<( - msvc_iterator_classification::value - )>::template traits_ 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* - >::value> non_category_traits_select; - typedef non_category_traits_select::template non_category_traits 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::type iterator_category; -# endif - }; }; -} // namespace boost::detail::iterator_traits_ +template +struct iterator_traits_aux + : mpl::if_< + is_pointer + , pointer_iterator_traits + , non_pointer_iterator_traits + >::type +{ +}; template struct iterator_traits - : iterator_traits_::iterator_traits_select::value>::template traits +# ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION + : mpl::if_< + is_bad_output_iterator + , bad_output_iterator_traits + , iterator_traits_aux + >::type +# else + : iterator_traits_aux +# endif { - private: - typedef typename iterator_traits_::iterator_traits_select< - is_pointer::type>::value>::template traits traits; - 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; }; -namespace iterator_traits_ { +namespace iterator_traits_ +{ + template + struct iterator_difference + { + typedef typename iterator_traits::difference_type type; + }; -template -struct distance_select { - template - static typename ::boost::detail::iterator_traits::difference_type - distance(Iterator i1, const Iterator i2) - { - typename ::boost::detail::iterator_traits::difference_type result = 0; - while (i1 != i2) - { - ++i1; - ++result; - } - return result; - } -}; - -template <> -struct distance_select { - template - static typename ::boost::detail::iterator_traits::difference_type - distance(const Iterator i1, const Iterator i2) - { - return i2 - i1; - } -}; + template + struct distance_select + { + static Difference execute(Iterator i1, const Iterator i2, ...) + { + typename 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 -inline typename ::boost::detail::iterator_traits::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_category iterator_category; - return iterator_traits_::distance_select::distance(first, last); + + return iterator_traits_::distance_select::execute( + first, last, (iterator_category*)0); } # endif // workarounds