diff --git a/include/boost/iterator/iterator_adaptors.hpp b/include/boost/iterator/iterator_adaptors.hpp index 02616df..68ce444 100644 --- a/include/boost/iterator/iterator_adaptors.hpp +++ b/include/boost/iterator/iterator_adaptors.hpp @@ -7,14 +7,19 @@ #include #include #include + #include #include +#include + #include #include #include "boost/type_traits/detail/bool_trait_def.hpp" -#if BOOST_WORKAROUND(BOOST_MSVC, <= 1301) || BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) || BOOST_WORKAROUND(__MWERKS__, <= 0x3000) +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1301) \ + || BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \ + || BOOST_WORKAROUND(__MWERKS__, <= 0x3000) # define BOOST_NO_SFINAE // "Substitution Failure Is Not An Error not implemented" #endif @@ -25,9 +30,21 @@ #endif #if BOOST_WORKAROUND(__MWERKS__, <=0x2407) -# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working" +# define BOOST_NO_IS_CONVERTIBLE // "is_convertible doesn't work" #endif +#if BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \ + || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) +# define BOOST_NO_MPL_AUX_HAS_XXX // "MPL's has_xxx facility doesn't work" +#endif + +#ifdef BOOST_NO_MPL_AUX_HAS_XXX +# include +# include +# include +#endif + + namespace boost { namespace detail { @@ -86,12 +103,12 @@ namespace boost { // on operator implementation for consequences. // template - struct is_interoperable : + struct is_interoperable #ifdef BOOST_NO_IS_CONVERTIBLE - mpl::true_c + : mpl::true_c #else - mpl::logical_or< is_convertible< A, B >, - is_convertible< B, A > > + : mpl::logical_or< is_convertible< A, B >, + is_convertible< B, A > > #endif { }; @@ -105,12 +122,16 @@ namespace boost { template - struct enable_if_interoperable : - enabled< is_interoperable::value >::template base + struct enable_if_interoperable +# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) + : enabled< is_interoperable::value >::template base +# else + : mpl::identity +# endif { -#if BOOST_WORKAROUND(BOOST_MSVC, <=1200) - typedef typename enabled< is_interoperable::value >::template base::type type; -#endif +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + typedef Return type; +# endif }; // @@ -161,24 +182,19 @@ namespace boost { // false positives for user/library defined iterator types. See comments // on operator implementation for consequences. // -#ifdef BOOST_NO_IS_CONVERTIBLE template - struct enable_if_convertible - { - typedef detail::enable_type type; - }; + struct enable_if_convertible +#if !defined(BOOST_NO_IS_CONVERTIBLE) && !defined(BOOST_NO_SFINAE) + : detail::enabled< is_convertible::value >::template base #else - template - struct enable_if_convertible : - detail::enabled< is_convertible::value >::template base + : mpl::identity +#endif { -#if BOOST_WORKAROUND(BOOST_MSVC, <=1200) - typedef typename detail::enabled< is_convertible::value >::template base::type type; -#endif +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + typedef detail::enable_type type; +# endif }; -#endif // // Helper class for granting access to the iterator core interface. @@ -708,31 +724,44 @@ namespace boost { { // // Detection for whether a type has a nested `element_type' - // typedef. Used to detect smart pointers. We're having trouble - // auto-detecting smart pointers with gcc-2.95 via the nested - // element_type member. However, we really ought to have a - // specializable is_pointer template which can be used instead with - // something like boost/python/pointee.hpp to find the value_type. + // typedef. Used to detect smart pointers. For compilers not + // supporting mpl's has_xxx, we supply specialzations. However, we + // really ought to have a specializable is_pointer template which + // can be used instead with something like + // boost/python/pointee.hpp to find the value_type. // +# if !defined BOOST_NO_MPL_AUX_HAS_XXX namespace aux { BOOST_MPL_HAS_XXX_TRAIT_DEF(element_type) - } + } template struct has_element_type : mpl::if_< - is_class -// gcc 2.95 doesn't seem to be able to detect element_type without barfing -# if BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) - , mpl::bool_c -# else - , aux::has_element_type -# endif - , mpl::bool_c - >::type + is_class + , aux::has_element_type + , mpl::false_c + >::type { }; +# else + template + struct has_element_type + : mpl::false_c {}; + + template + struct has_element_type > + : mpl::true_c {}; + + template + struct has_element_type > + : mpl::true_c {}; + + template + struct has_element_type > + : mpl::true_c {}; +# endif // Metafunction returning the nested element_type typedef template @@ -750,11 +779,11 @@ namespace boost { // to deduce the default types template struct indirect_defaults - : mpl::if_c< - has_element_type::value_type>::value - , smart_pointer_traits::value_type> - , iterator_traits::value_type> - >::type + : mpl::if_< + has_element_type::value_type> + , smart_pointer_traits::value_type> + , iterator_traits::value_type> + >::type { typedef typename iterator_traits::iterator_category iterator_category; typedef typename iterator_traits::difference_type difference_type; @@ -824,14 +853,9 @@ namespace boost { // clean up local workaround macros // -#ifdef BOOST_NO_SFINAE -# undef BOOST_NO_SFINAE -#endif - +#undef BOOST_NO_SFINAE #undef BOOST_ARG_DEP_TYPENAME - -#ifdef BOOST_NO_IS_CONVERTIBLE -# undef BOOST_NO_IS_CONVERTIBLE -#endif +#undef BOOST_NO_IS_CONVERTIBLE +#undef BOOST_NO_MPL_AUX_HAS_XXX #endif // BOOST_ITERATOR_ADAPTORS_HPP diff --git a/test/indirect_iterator_test.cpp b/test/indirect_iterator_test.cpp index bae16b5..0e7f224 100644 --- a/test/indirect_iterator_test.cpp +++ b/test/indirect_iterator_test.cpp @@ -26,22 +26,64 @@ #include #include -#include #include +#if defined(BOOST_MSVC_STD_ITERATOR) \ + || BOOST_WORKAROUND(_CPPLIB_VER, <= 310) \ + || BOOST_WORKAROUND(__GNUC__, <= 2 && !defined(__SGI_STL_PORT)) + +// std container random-access iterators don't support mutable/const +// interoperability (but may support const/mutable interop). +# define NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY +# define NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY + +#endif + +#if defined(BOOST_MSVC_STD_ITERATOR) \ +|| defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +// No working iterator_traits implementation, so we must use deque +# define RA_CONTAINER std::deque +# include + +# ifdef NO_MUTABLE_CONST_STD_DEQUE_ITERATOR_INTEROPERABILITY +# define NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY +# endif + +#else + +# define RA_CONTAINER std::vector +# include + +#endif + struct my_iterator_tag : public std::random_access_iterator_tag { }; using boost::dummyT; -typedef std::deque storage; -typedef std::deque pointer_deque; +typedef RA_CONTAINER storage; +typedef RA_CONTAINER pointer_ra_container; typedef std::set iterator_set; +// Something has to be done about putting this in the lib +template +struct indirect_const_iterator_traits + : boost::detail::indirect_defaults +{ + typedef boost::detail::indirect_defaults base; + typedef typename base::value_type const& reference; + typedef typename base::value_type const* pointer; +}; + template struct indirect_iterator_pair_generator { typedef boost::indirect_iterator iterator; - typedef boost::indirect_iterator const_iterator; + + typedef boost::indirect_iterator< + typename Container::iterator + , indirect_const_iterator_traits + > const_iterator; }; #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION @@ -70,40 +112,37 @@ void more_indirect_iterator_tests() storage store(1000); std::generate(store.begin(), store.end(), rand); - pointer_deque ptr_deque; + pointer_ra_container ptr_ra_container; iterator_set iter_set; for (storage::iterator p = store.begin(); p != store.end(); ++p) { - ptr_deque.push_back(&*p); + ptr_ra_container.push_back(&*p); iter_set.insert(p); } - typedef indirect_iterator_pair_generator IndirectDeque; + typedef indirect_iterator_pair_generator indirect_ra_container; - IndirectDeque::iterator db(ptr_deque.begin()); - IndirectDeque::iterator de(ptr_deque.end()); + indirect_ra_container::iterator db(ptr_ra_container.begin()); + indirect_ra_container::iterator de(ptr_ra_container.end()); assert(static_cast(de - db) == store.size()); assert(db + store.size() == de); - IndirectDeque::const_iterator dci(db); + indirect_ra_container::const_iterator dci = db; assert(dci == db); - // Older Dinkumware and GCC standard lib don't supply symmetric constant/mutable - // iterator operators -#if !defined(BOOST_MSVC_STD_ITERATOR) \ - && !BOOST_WORKAROUND(_CPPLIB_VER, <= 310) \ - && !BOOST_WORKAROUND(__GNUC__, <= 2 && !defined(__SGI_STL_PORT)) - +#ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY assert(db == dci); +#endif assert(dci != de); assert(dci < de); assert(dci <= de); -#endif +#ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY assert(de >= dci); assert(de > dci); +#endif dci = de; assert(dci == de); @@ -121,6 +160,11 @@ void more_indirect_iterator_tests() indirect_set_iterator se(iter_set.end()); const_indirect_set_iterator sci(iter_set.begin()); assert(sci == sb); + +# ifndef NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY + assert(se != sci); +# endif + assert(sci != se); sci = se; assert(sci == se); @@ -140,7 +184,7 @@ main() dummyT(3), dummyT(4), dummyT(5) }; const int N = sizeof(array)/sizeof(dummyT); - typedef std::deque > shared_t; + typedef RA_CONTAINER > shared_t; shared_t shared; // Concept checks @@ -148,12 +192,9 @@ main() typedef boost::indirect_iterator iter_t; typedef boost::indirect_iterator c_iter_t; - // Older Dinkumware and GCC standard lib don't supply symmetric constant/mutable - // iterator operators -#if !defined(BOOST_MSVC_STD_ITERATOR) && (!defined(_CPPLIB_VER) || _CPPLIB_VER > 310) \ - && (__GNUC__ != 2 || defined(__SGI_STL_PORT)) +# ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY boost::function_requires< boost_concepts::InteroperableConcept >(); -#endif +# endif } // Test indirect_iterator_generator @@ -167,22 +208,15 @@ main() typedef boost::indirect_iterator indirect_iterator; - typedef boost::indirect_iterator const_indirect_iterator; + typedef boost::indirect_iterator > + const_indirect_iterator; indirect_iterator i(ptr); boost::random_access_iterator_test(i, N, array); -#if __GNUC__ != 2 - // We're having trouble auto-detecting smart pointers with - // gcc-2.95 via the nested element_type member. However, we - // really ought to have a specializable is_pointer template - // which can be used instead with something like - // boost/python/pointee.hpp to find the value_type. - boost::random_access_iterator_test( boost::indirect_iterator(shared.begin()) , N, array); -#endif boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);