From 9b38c048b64af750d55ca8aea1f14fcec0f0fab0 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Mon, 19 Feb 2001 22:51:32 +0000 Subject: [PATCH] Improved workarounds for stock MSVC6; use yes_type and no_type from type_traits.hpp; stopped trying to remove_cv before detecting is_pointer, in honor of the new type_traits semantics. [SVN r9282] --- include/boost/detail/iterator.hpp | 133 ++++++++++++++++++++++-------- 1 file changed, 100 insertions(+), 33 deletions(-) diff --git a/include/boost/detail/iterator.hpp b/include/boost/detail/iterator.hpp index 0d9ceff..29b4346 100644 --- a/include/boost/detail/iterator.hpp +++ b/include/boost/detail/iterator.hpp @@ -23,6 +23,10 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 19 Feb 2001 - Improved workarounds for stock MSVC6; use yes_type and +// no_type from type_traits.hpp; stopped trying to remove_cv +// before detecting is_pointer, in honor of the new type_traits +// semantics. (David Abrahams) // 13 Feb 2001 - Make it work with nearly all standard-conforming iterators // under raw VC6. The one category remaining which will fail is // that of iterators derived from std::iterator but not @@ -47,6 +51,13 @@ # include # include +# if defined(BOOST_MSVC) && !defined(__SGI_STL_PORT) +# include +# include +# include +# 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 // container iterators have _Iterator_category. @@ -70,9 +81,6 @@ using std::iterator_traits; using std::distance; # else -typedef char yes_result; -typedef double no_result; - // Workarounds for less-capable implementations template struct iterator_traits_select; @@ -84,12 +92,12 @@ template <> struct iterator_traits_select { typedef std::ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; + typedef Ptr pointer; #ifdef BOOST_MSVC // 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 pointer; typedef undefined reference; #endif }; @@ -97,8 +105,8 @@ template <> struct iterator_traits_select # ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF -no_result bad_category_helper(...); -template yes_result bad_category_helper(std::_DBG_iter*); +no_type bad_category_helper(...); +template yes_type bad_category_helper(std::_DBG_iter*); template struct bad_category_select; template <> @@ -120,7 +128,7 @@ struct iterator_category_select private: static Iterator p; enum { has_bad_category - = sizeof(bad_category_helper(&p)) == sizeof(yes_result) }; + = sizeof(bad_category_helper(&p)) == sizeof(yes_type) }; typedef bad_category_select category_select; public: typedef typename category_select::template category::type type; @@ -155,24 +163,22 @@ struct bad_output_iterator_select # endif # if defined(BOOST_MSVC) && !defined(__SGI_STL_PORT) -template struct msvc_traits_select; -template <> struct msvc_traits_select +// 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 traits_ // calling this "traits" will confuse VC. - { - typedef typename Iterator::distance_type difference_type; - typedef typename Iterator::value_type value_type; - typedef undefined pointer; - typedef undefined reference; - }; -}; - -template <> struct msvc_traits_select -{ - template - struct traits_ { typedef typename Iterator::difference_type difference_type; typedef typename Iterator::value_type value_type; @@ -181,20 +187,81 @@ template <> struct msvc_traits_select }; }; -template -yes_result is_std_iterator_helper(const volatile std::iterator*); -no_result is_std_iterator_helper(...); +template <> struct msvc_traits_select +{ + 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; + }; +}; +template <> struct msvc_traits_select +{ + 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; + }; +}; + +template <> struct msvc_traits_select +{ + 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? +template +yes_type is_std_iterator_helper(const volatile std::iterator*); +no_type is_std_iterator_helper(...); + +// Is the iterator derived from boost::iterator? template -yes_result is_boost_iterator_helper(const volatile boost::iterator*); -no_result is_boost_iterator_helper(...); +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 std::_Tree::iterator*); +template +yes_type is_mutable_iterator_helper(const volatile std::list::iterator*); +template +yes_type is_mutable_iterator_helper(const volatile 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 has_msvc_std_iterator_traits -{ - BOOST_STATIC_CONSTANT(bool, value = - (sizeof(is_std_iterator_helper((T*)0)) == sizeof(yes_result) - && sizeof(is_boost_iterator_helper((T*)0)) == sizeof(no_result))); +struct msvc_iterator_classification { + enum { + 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 + }; }; # endif @@ -205,7 +272,7 @@ template <> struct iterator_traits_select { # if defined(BOOST_MSVC) && !defined(__SGI_STL_PORT) typedef msvc_traits_select<( - has_msvc_std_iterator_traits::value + msvc_iterator_classification::value )>::template traits_ inner_traits; typedef typename inner_traits::difference_type difference_type; @@ -241,7 +308,7 @@ template <> struct iterator_traits_select template struct iterator_traits - : iterator_traits_select::type>::value>::template traits + : iterator_traits_select::value>::template traits { private: typedef typename iterator_traits_select<