From 5cf6dd58286ed2fc2325cc8408dfd4648ecb2a08 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 5 Mar 2001 20:01:01 +0000 Subject: [PATCH] Join ralf_grosse_kunstleve with HEAD [SVN r9444] --- include/boost/detail/iterator.hpp | 311 ++++++++++++++++++++---- include/boost/detail/numeric_traits.hpp | 82 +++---- 2 files changed, 307 insertions(+), 86 deletions(-) diff --git a/include/boost/detail/iterator.hpp b/include/boost/detail/iterator.hpp index 17b3344..d97bfd7 100644 --- a/include/boost/detail/iterator.hpp +++ b/include/boost/detail/iterator.hpp @@ -11,15 +11,68 @@ // std::distance() // // ...for all compilers and iterators +// +// Additionally, if X is a pointer +// std::iterator_traits::pointer + +// Otherwise, if partial specialization is supported or X is not a pointer +// std::iterator_traits::value_type +// 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 +// 04 Mar 2001 - More attempted fixes for Intel C++ (David Abrahams) +// 03 Mar 2001 - Put all implementation into namespace +// boost::detail::iterator_traits_. Some progress made on fixes +// for Intel compiler. (David Abrahams) +// 02 Mar 2001 - Changed BOOST_MSVC to BOOST_MSVC_STD_ITERATOR in a few +// places. (Jeremy Siek) +// 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 +// boost::iterator and which redefine difference_type. +// 11 Feb 2001 - Clean away code which can never be used (David Abrahams) +// 09 Feb 2001 - Always have a definition for each traits member, even if it +// can't be properly deduced. These will be incomplete types in +// some cases (undefined), but it helps suppress MSVC errors +// elsewhere (David Abrahams) +// 07 Feb 2001 - Support for more of the traits members where possible, making +// this useful as a replacement for std::iterator_traits when +// used as a default template parameter. +// 06 Feb 2001 - Removed useless #includes of standard library headers +// (David Abrahams) #ifndef ITERATOR_DWA122600_HPP_ # define ITERATOR_DWA122600_HPP_ # include # include +# include # include # include +# if defined(BOOST_MSVC_STD_ITERATOR) +# include +# include +# include +# if 0 && defined(__ICL) // Re-enable this to pick up the Intel fixes where they left off +# include +# include +# endif +# 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. @@ -37,25 +90,18 @@ # endif // STLPort <= 4.1b4 && no partial specialization -# ifdef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF -# include -# include -# include -# include -# include -# include -# include -# include -# include -# endif - namespace boost { namespace detail { -# if !defined(BOOST_NO_STD_ITERATOR_TRAITS) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +# 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_ { + // Workarounds for less-capable implementations template struct iterator_traits_select; + +template struct undefined; template <> struct iterator_traits_select { template @@ -63,13 +109,25 @@ 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 reference; +#endif }; }; +typedef char yes_type; +typedef double no_type; + # 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 <> @@ -91,7 +149,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; @@ -100,42 +158,210 @@ struct iterator_category_select # endif # ifdef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION -template struct bad_difference_select; +template struct bad_output_iterator_select; template <> -struct bad_difference_select +struct bad_output_iterator_select { template - struct difference { typedef void type; }; + struct non_category_traits { + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + }; }; template <> -struct bad_difference_select +struct bad_output_iterator_select { template - struct difference { typedef typename Iterator::difference_type type; }; + 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; + }; +}; +# endif + +# if defined(BOOST_MSVC_STD_ITERATOR) + +// 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::difference_type difference_type; + typedef typename Iterator::value_type value_type; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::reference reference; + }; +}; + +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? +no_type is_std_iterator_helper(...); +template +yes_type is_std_iterator_helper(const volatile std::iterator*); + +#if 0 && defined(__ICL) // re-enable this to pick up with the Intel C++ fixes where they left off +// for some reason, it's unable to make the deduction of derivation :( +template +yes_type is_std_iterator_helper(const volatile typename std::_Tree::iterator*); +template +yes_type is_std_iterator_helper(const volatile typename std::list::iterator*); +template +yes_type is_std_iterator_helper(const volatile typename std::deque::iterator*); + +template +yes_type is_std_iterator_helper(const volatile typename std::_Tree::const_iterator*); +template +yes_type is_std_iterator_helper(const volatile typename std::list::const_iterator*); +template +yes_type is_std_iterator_helper(const volatile typename std::deque::const_iterator*); + +template +yes_type is_std_iterator_helper(const volatile std::reverse_iterator*); +template +yes_type is_std_iterator_helper(const volatile std::reverse_bidirectional_iterator*); +template +yes_type is_std_iterator_helper(const volatile std::back_insert_iterator*); +template +yes_type is_std_iterator_helper(const volatile std::front_insert_iterator*); +template +yes_type is_std_iterator_helper(const volatile std::insert_iterator*); +template +yes_type is_std_iterator_helper(const volatile std::istream_iterator*); +template +yes_type is_std_iterator_helper(const volatile std::istreambuf_iterator*); +template +yes_type is_std_iterator_helper(const volatile std::ostreambuf_iterator*); +template +yes_type is_std_iterator_helper(const volatile std::raw_storage_iterator*); +#endif + +// 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(...); + +#if 0 && defined(__ICL) +// this static assertion highlights the first of a few problems getting this to +// work with the Intel compiler. We can get past it with the many definitions +// for is_std_iterator_helper above, but there are other failures. +template struct check; +template <> struct check {}; +check<(sizeof(is_std_iterator_helper((std::istream_iterator*)0)) == sizeof(yes_type))> assertion; +#endif + +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 + ); }; -yes_result bad_output_iterator_helper(std::iterator*); -no_result bad_output_iterator_helper(...); # endif template <> struct iterator_traits_select { template struct traits -# if defined(BOOST_NO_STD_ITERATOR_TRAITS) { -# if defined(BOOST_MSVC) && !defined(__SGI_STL_PORT) - typedef typename Iterator::distance_type difference_type; +# if defined(BOOST_MSVC_STD_ITERATOR) + 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::difference_type difference_type; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::reference reference; # else - private: - // static Iterator *p; - typedef bad_difference_select< + typedef bad_output_iterator_select< is_convertible* - >::value> difference_type_select; + >::value> non_category_traits_select; + typedef non_category_traits_select::template non_category_traits non_category_traits; public: - typedef typename difference_type_select::template difference::type difference_type; + 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) @@ -144,25 +370,26 @@ template <> struct iterator_traits_select typedef typename iterator_category_select::type iterator_category; # endif }; -# else - { - typedef typename std::iterator_traits::difference_type difference_type; - typedef typename std::iterator_traits::iterator_category iterator_category; - }; -# endif }; +} // namespace boost::detail::iterator_traits_ + template struct iterator_traits + : iterator_traits_::iterator_traits_select::value>::template traits { private: - typedef iterator_traits_select::type>::value> select; - typedef typename select::template traits traits; + 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_ { + template struct distance_select { template @@ -189,16 +416,18 @@ struct distance_select { } }; +} // namespace boost::detail::iterator_traits_ + template inline typename ::boost::detail::iterator_traits::difference_type distance(const Iterator& first, const Iterator& last) { typedef typename ::boost::detail::iterator_traits::iterator_category iterator_category; - return distance_select::distance(first, last); + return iterator_traits_::distance_select::distance(first, last); } # endif // workarounds -}} +}} // namespace boost::detail # undef BOOST_BAD_CONTAINER_ITERATOR_CATEGORY_TYPEDEF # undef BOOST_BAD_OUTPUT_ITERATOR_SPECIALIZATION diff --git a/include/boost/detail/numeric_traits.hpp b/include/boost/detail/numeric_traits.hpp index 9701ec6..785a61e 100644 --- a/include/boost/detail/numeric_traits.hpp +++ b/include/boost/detail/numeric_traits.hpp @@ -49,11 +49,18 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 11 Feb 2001 - Use BOOST_STATIC_CONSTANT (David Abrahams) +// 11 Feb 2001 - Rolled back ineffective Borland-specific code +// (David Abrahams) +// 10 Feb 2001 - Rolled in supposed Borland fixes from John Maddock, but +// not seeing any improvement yet (David Abrahams) +// 06 Feb 2001 - Factored if_true out into boost/detail/select_type.hpp +// (David Abrahams) // 23 Jan 2001 - Fixed logic of difference_type selection, which was // completely wack. In the process, added digit_traits<> // to compute the number of digits in intmax_t even when -// not supplied by numeric_limits<>. -// 21 Jan 2001 - Created +// not supplied by numeric_limits<>. (David Abrahams) +// 21 Jan 2001 - Created (David Abrahams) #ifndef BOOST_NUMERIC_TRAITS_HPP_DWA20001901 # define BOOST_NUMERIC_TRAITS_HPP_DWA20001901 @@ -62,31 +69,13 @@ # include # include # include +# include # ifndef BOOST_NO_LIMITS # include # endif namespace boost { namespace detail { - // Template class if_true -- select among 2 types based on a bool constant expression - // Usage: - // typename if_true<(bool_const_expression)>::template then::type - template struct if_true; - - template <> - struct if_true - { - template - struct then { typedef T1 type; }; - }; - - template <> - struct if_true - { - template - struct then { typedef T2 type; }; - }; - // Template class is_signed -- determine whether a numeric type is signed // Requires that T is constructable from the literals -1 and 0. Compile-time // error results if that requirement is not met (and thus signedness is not @@ -94,7 +83,11 @@ namespace boost { namespace detail { template struct is_signed { - enum { value = (Number(-1) < Number(0)) }; +#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_MSVC) + BOOST_STATIC_CONSTANT(bool, value = (Number(-1) < Number(0))); +#else + BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_signed); +#endif }; # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS @@ -108,7 +101,7 @@ namespace boost { namespace detail { { template struct traits { - enum { digits = std::numeric_limits::digits }; + BOOST_STATIC_CONSTANT(int, digits = std::numeric_limits::digits); }; }; @@ -117,26 +110,26 @@ namespace boost { namespace detail { { template struct traits { - enum { digits = sizeof(T) * std::numeric_limits::digits - - (is_signed::value ? 1 : 0) - }; + BOOST_STATIC_CONSTANT(int, digits = ( + sizeof(T) * std::numeric_limits::digits + - (is_signed::value ? 1 : 0)) + ); }; }; // here's the "usable" template template struct digit_traits { - enum { - digits = digit_traits_select< - std::numeric_limits::is_specialized - >::template traits::digits - }; + typedef digit_traits_select< + ::std::numeric_limits::is_specialized> selector; + typedef typename selector::template traits traits; + BOOST_STATIC_CONSTANT(int, digits = traits::digits); }; -#endif +#endif // Template class integer_traits -- traits of various integer types // This should probably be rolled into boost::integer_traits one day, but I -// need it to work without + // need it to work without template struct integer_traits { @@ -147,37 +140,36 @@ namespace boost { namespace detail { # ifdef BOOST_MSVC // for some reason, MSVC asserts when it shouldn't unless we make these // local definitions - enum { - is_integer = x::is_integer, - is_specialized = x::is_specialized - }; + BOOST_STATIC_CONSTANT(bool, is_integer = x::is_integer); + BOOST_STATIC_CONSTANT(bool, is_specialized = x::is_specialized); + BOOST_STATIC_ASSERT(is_integer); BOOST_STATIC_ASSERT(is_specialized); # endif public: typedef typename - if_true<(x::is_signed - && (!x::is_bounded + if_true<(int(x::is_signed) + && (!int(x::is_bounded) // digits is the number of no-sign bits - || (x::digits + 1 >= digit_traits::digits)))>::template then< + || (int(x::digits) + 1 >= digit_traits::digits)))>::template then< Integer, - typename if_true<(x::digits + 1 < digit_traits::digits)>::template then< + typename if_true<(int(x::digits) + 1 < digit_traits::digits)>::template then< signed int, - typename if_true<(x::digits + 1 < digit_traits::digits)>::template then< + typename if_true<(int(x::digits) + 1 < digit_traits::digits)>::template then< signed long, // else intmax_t >::type>::type>::type difference_type; -# else +#else BOOST_STATIC_ASSERT(boost::is_integral::value); - + typedef typename if_true<(sizeof(Integer) >= sizeof(intmax_t))>::template then< - typename if_true::value>::template then< + typename if_true<(is_signed::value)>::template then< Integer, intmax_t >::type,