diff --git a/include/boost/iterator/counting_iterator.hpp b/include/boost/iterator/counting_iterator.hpp new file mode 100755 index 0000000..42b4c1d --- /dev/null +++ b/include/boost/iterator/counting_iterator.hpp @@ -0,0 +1,194 @@ +// Copyright David Abrahams 2003. 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. +#ifndef COUNTING_ITERATOR_DWA200348_HPP +# define COUNTING_ITERATOR_DWA200348_HPP + +# include +# include +# include +# include +# include +# include + +namespace boost { + +template class counting_iterator; + +namespace detail +{ + // Try to detect numeric types at compile time in ways compatible + // with the limitations of the compiler and library. + template + struct is_numeric_impl + { + // For a while, this wasn't true, but we rely on it below. This is a regression assert. + BOOST_STATIC_ASSERT(::boost::is_integral::value); + +# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + +# if defined(BOOST_HAS_LONG_LONG) + BOOST_STATIC_CONSTANT( + bool, value = ( + std::numeric_limits::is_specialized + | boost::is_same::value + | boost::is_same::value + )); +# else + BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); +# endif + +# else + +# if !defined(__BORLANDC__) + BOOST_STATIC_CONSTANT( + bool, value = ( + boost::is_convertible::value + && boost::is_convertible::value + )); +# else + BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic::value); +# endif + +# endif + }; + + template + struct is_numeric + : mpl::bool_<(::boost::detail::is_numeric_impl::value)> + {}; + + template + struct numeric_difference + { + typedef typename boost::detail::numeric_traits::difference_type type; + }; + + BOOST_STATIC_ASSERT(is_numeric::value); + template + struct counting_iterator_base + { + typedef typename mpl::apply_if< + is_same + , mpl::apply_if< + is_numeric + , mpl::identity + , BOOST_ITERATOR_CATEGORY + > + , mpl::identity + >::type category; + + typedef typename mpl::apply_if< + is_same + , mpl::apply_if< + is_numeric + , numeric_difference + , iterator_difference + > + , mpl::identity + >::type difference; + + typedef iterator_adaptor< + counting_iterator // self + , Incrementable // Base + , Incrementable // value_type + , category + , Incrementable const& // reference + , Incrementable const* // pointer + , difference + > type; + }; + + // Template class distance_policy_select -- choose a policy for computing the + // distance between counting_iterators at compile-time based on whether or not + // the iterator wraps an integer or an iterator, using "poor man's partial + // specialization". + + template struct distance_policy_select; + + // A policy for wrapped iterators + template + struct iterator_distance + { + static Difference distance(Incrementable1 x, Incrementable2 y) + { + return boost::detail::distance(x, y); + } + }; + + // A policy for wrapped numbers + template + struct number_distance + { + static Difference distance(Incrementable1 x, Incrementable2 y) + { + return numeric_distance(x, y); + } + }; +} + +template +class counting_iterator + : public detail::counting_iterator_base::type +{ + typedef typename detail::counting_iterator_base::type super_t; + friend class iterator_core_access; + + public: + typedef typename super_t::difference_type difference_type; + + counting_iterator() { } + + counting_iterator(counting_iterator const& rhs) : super_t(rhs.base()) {} + + counting_iterator(Incrementable x) + : super_t(x) + { + } + +# if 0 + template + counting_iterator( + counting_iterator const& t + , typename enable_if_convertible::type* = 0 + ) + : super_t(t.base()) + {} +# endif + + private: + + typename super_t::reference dereference() const + { + return this->base_reference(); + } + + template + difference_type + distance_to(counting_iterator const& y) const + { + typedef typename mpl::if_< + detail::is_numeric + , detail::number_distance + , detail::iterator_distance + >::type d; + + return d::distance(this->base(), y.base()); + } +}; + +// Manufacture a counting iterator for an arbitrary incrementable type +template +inline counting_iterator +make_counting_iterator(Incrementable x) +{ + typedef counting_iterator result_t; + return result_t(x); +} + + +} // namespace boost::iterator + +#endif // COUNTING_ITERATOR_DWA200348_HPP diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp index 1668af5..5722fa0 100644 --- a/include/boost/iterator/detail/categories.hpp +++ b/include/boost/iterator/detail/categories.hpp @@ -13,42 +13,98 @@ #include #include #include +#include +#include #include #include +#include #include #if BOOST_WORKAROUND(__MWERKS__, <=0x2407) # define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working" #endif -namespace boost { +namespace boost +{ + + // faked new old-style categories needed to make new->old mapping + // work + namespace detail + { + struct null_category_tag {}; + struct input_output_iterator_tag : std::input_iterator_tag, std::output_iterator_tag {}; + } + + // + // Access Categories + // + struct readable_iterator_tag + { + typedef std::input_iterator_tag max_category; + }; + + struct writable_iterator_tag + { + typedef std::output_iterator_tag max_category; + }; + + struct swappable_iterator_tag + { + typedef detail::null_category_tag max_category; + }; + + struct readable_writable_iterator_tag + : virtual readable_iterator_tag + , virtual writable_iterator_tag + , virtual swappable_iterator_tag + { + typedef detail::input_output_iterator_tag max_category; + }; + + struct readable_lvalue_iterator_tag + : virtual readable_iterator_tag + { + typedef std::random_access_iterator_tag max_category; + }; + + struct writable_lvalue_iterator_tag + : virtual public readable_writable_iterator_tag + , virtual public readable_lvalue_iterator_tag + { + typedef std::random_access_iterator_tag max_category; + }; // - // Categories - // - // !! Fix detection functions if categories - // are changed. - // - - // Return Type Categories - struct readable_iterator_tag { }; - struct writable_iterator_tag { }; - struct swappable_iterator_tag : - virtual public readable_iterator_tag, // Not sure about this change -JGS - virtual public writable_iterator_tag { }; - struct constant_lvalue_iterator_tag : - virtual public readable_iterator_tag { }; - struct mutable_lvalue_iterator_tag : - virtual public swappable_iterator_tag, - virtual public constant_lvalue_iterator_tag { }; - // Traversal Categories - struct input_traversal_tag { }; - struct output_traversal_tag { }; - struct forward_traversal_tag : virtual public input_traversal_tag, - virtual public output_traversal_tag { }; - struct bidirectional_traversal_tag : virtual public forward_traversal_tag { }; - struct random_access_traversal_tag : virtual public bidirectional_traversal_tag { }; + // + struct incrementable_iterator_tag + { + typedef std::output_iterator_tag max_category; + }; + + struct single_pass_iterator_tag + : incrementable_iterator_tag + { + typedef detail::input_output_iterator_tag max_category; + }; + + struct forward_traversal_tag + : single_pass_iterator_tag + { + typedef std::forward_iterator_tag max_category; + }; + + struct bidirectional_traversal_tag + : forward_traversal_tag + { + typedef std::bidirectional_iterator_tag max_category; + }; + + struct random_access_traversal_tag + : bidirectional_traversal_tag + { + typedef std::random_access_iterator_tag max_category; + }; struct error_iterator_tag { }; @@ -57,384 +113,162 @@ namespace boost { // // Tag detection meta functions // - // Needed to work with compilers - // without working is_convertible - // - -#ifndef BOOST_NO_IS_CONVERTIBLE - template - struct is_input_iterator : - is_convertible - { - }; - - template - struct is_output_iterator : - is_convertible - { - }; - - template - struct is_forward_iterator : - is_convertible - { - }; - - template - struct is_bidirectional_iterator : - is_convertible - { - }; - - template - struct is_random_access_iterator : - is_convertible - { - }; - - template - struct is_readable_iterator : - is_convertible - { }; - - template - struct is_writable_iterator : - is_convertible - { }; - - template - struct is_swappable_iterator : - is_convertible - { }; - - template - struct is_constant_lvalue_iterator : - is_convertible - { }; - - template - struct is_mutable_lvalue_iterator : - is_convertible - { }; - - template - struct is_input_traversal_iterator : - is_convertible - { }; - - template - struct is_output_traversal_iterator : - is_convertible - { }; - - template - struct is_forward_traversal_iterator : - is_convertible - { }; - - template - struct is_bidirectional_traversal_iterator : - is_convertible - { }; - - template - struct is_random_access_traversal_iterator : - is_convertible - { }; - -#else - // - // We cannot detect the iterator category for custom - // tag types. For custom tag types false_ is returned - // - // As a result the std iterator category detection functions - // can't detect the iterator category of the new iterator_tag template. - // - - // - // std iterator categories - // - - template - struct is_random_access_iterator : - mpl::false_ - {}; - - template <> - struct is_random_access_iterator : - mpl::true_ - {}; - - template - struct is_bidirectional_iterator : - is_random_access_iterator< Category > - {}; - - template <> - struct is_bidirectional_iterator : - mpl::true_ - {}; - - template - struct is_forward_iterator : - is_bidirectional_iterator< Category > - {}; - - template <> - struct is_forward_iterator : - mpl::true_ - {}; - - template - struct is_output_iterator : - is_forward_iterator< Category > - {}; - - template <> - struct is_output_iterator : - mpl::true_ - {}; - - template - struct is_input_iterator : - is_forward_iterator< Category > - {}; - - template <> - struct is_input_iterator : - mpl::true_ - {}; - - // - // Return type - // - // The nested is_category template class are used for - // minimum category detection in iterator_adaptors. - // They are basically a poore mans is_derived replacement. - // - // A implementation may look like this - // - // template - // struct min_cat - // : mpl::if_< is_return_category< Cat1 >::template is_category< Cat2 >, - // Cat1, - // mpl::if_< is_return_category::template is_category, - // Cat2, - // error_type - // > - // > {}; - - template - struct is_mutable_lvalue_iterator : - mpl::false_ - { - template - struct is_category - : boost::mpl::false_ {}; - }; - - template <> - struct is_mutable_lvalue_iterator : - mpl::true_ - { - template - struct is_category - : is_mutable_lvalue_iterator {}; - }; - - template - struct is_constant_lvalue_iterator : - is_mutable_lvalue_iterator - {}; - - template <> - struct is_constant_lvalue_iterator : - mpl::true_ - { - template - struct is_category - : is_constant_lvalue_iterator {}; - }; - - template - struct is_swappable_iterator : - is_constant_lvalue_iterator - {}; - - template <> - struct is_swappable_iterator : - mpl::true_ - { - template - struct is_category - : is_swappable_iterator {}; - }; - - template - struct is_readable_iterator : - mpl::if_< is_swappable_iterator, - is_swappable_iterator, - is_constant_lvalue_iterator >::type - {}; - - template <> - struct is_readable_iterator : - mpl::true_ - { - template - struct is_category - : is_readable_iterator {}; - }; - - template - struct is_writable_iterator : - is_swappable_iterator - {}; - - template <> - struct is_writable_iterator : - mpl::true_ - { - template - struct is_category - : is_writable_iterator {}; - }; - - template - struct is_return_category - : mpl::if_< is_writable_iterator, - is_writable_iterator, - is_readable_iterator >::type - { - }; - - // - // Traversal - // - - template - struct is_random_access_traversal_iterator : - mpl::false_ - { - template - struct is_category - : boost::mpl::false_ {}; - }; - - template <> - struct is_random_access_traversal_iterator : - mpl::true_ - { - template - struct is_category - : is_random_access_traversal_iterator {}; - }; - - template - struct is_bidirectional_traversal_iterator : - is_random_access_traversal_iterator< Category > - {}; - - template <> - struct is_bidirectional_traversal_iterator : - mpl::true_ - { - template - struct is_category - : is_bidirectional_traversal_iterator {}; - }; - - template - struct is_forward_traversal_iterator : - is_bidirectional_traversal_iterator< Category > - {}; - - template <> - struct is_forward_traversal_iterator : - mpl::true_ - { - template - struct is_category - : is_forward_traversal_iterator {}; - }; - - template - struct is_input_traversal_iterator : - is_forward_traversal_iterator< Category > - {}; - - template <> - struct is_input_traversal_iterator : - mpl::true_ - { - template - struct is_category - : is_input_traversal_iterator {}; - }; - - template - struct is_output_traversal_iterator : - is_forward_traversal_iterator< Category > - {}; - - template <> - struct is_output_traversal_iterator : - mpl::true_ - { - template - struct is_category - : is_output_traversal_iterator {}; - }; - - template - struct is_traversal_category - : mpl::if_< is_input_traversal_iterator, - is_input_traversal_iterator, - is_output_traversal_iterator >::type - {}; - -#endif - - // + // I bet this is defined somewhere else. Let's wait and see. - // struct error_type; -#ifdef BOOST_NO_IS_CONVERTIBLE - template - struct minimum_return_category - : mpl::if_< is_return_category< Cat1 >::template is_category< Cat2 >, - Cat1, - mpl::if_< is_return_category::template is_category, - Cat2, - error_type - > - > {}; - - template - struct minimum_traversal_category - : mpl::if_< is_traversal_category< Cat1 >::template is_category< Cat2 >, - Cat1, - mpl::if_< is_traversal_category::template is_category, - Cat2, - error_type - > - > {}; - - template - struct minimum_category_select - : mpl::if_< is_same< typename T1::type, error_type >, - T2, - T1 > - {}; -#endif - +#ifndef BOOST_NO_IS_CONVERTIBLE template - struct is_base_or_same : - mpl::or_< is_same< Base, Derived >, - is_base_and_derived< Base, Derived > > + struct is_same_or_derived +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + : mpl::or_< + is_same + , is_base_and_derived + > + {}; +# else + : is_base_and_derived {}; + template struct is_same_or_derived : mpl::true_ {}; +# endif + + template + struct is_tag + : mpl::or_< +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + is_same_or_derived +# else + is_base_and_derived +# endif + + // Because we can't actually get forward_iterator_tag to + // derive from input_output_iterator_tag, we need this + // case. + , mpl::and_< + is_same_or_derived + , is_same_or_derived + > + > + {}; + + +#else + template + struct is_tag; +#endif + + // Generate specializations which will allow us to find + // null_category_tag as a minimum old-style category for new-style + // iterators which don't have an actual old-style category. We + // need that so there is a valid base class for all new-style + // iterators. +#define BOOST_OLD_ITERATOR_CATEGORY(category) \ + template <> \ + struct is_tag \ + : mpl::true_ {}; + + BOOST_OLD_ITERATOR_CATEGORY(input_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(output_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(forward_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(bidirectional_iterator_tag) + BOOST_OLD_ITERATOR_CATEGORY(random_access_iterator_tag) +#undef BOOST_OLD_ITERATOR_CATEGORY + + template <> + struct is_tag + : mpl::true_ + { + }; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct is_tag : mpl::true_ + {}; + +# ifdef BOOST_NO_IS_CONVERTIBLE + // Workarounds for CWPro7 which can't detect derivation at + // compile-time. + + // Fact of life: we can only detect tag refinement relationships + // among predefined tags. + // + // Algorithm: + // is_tag(T,U) -> + // T == U + // || (exists d in derived_from(T) such that is_tag(d, U)) + // + // T == U case is handled above + + // false by default + template + struct is_tag_impl : mpl::false_ + {}; + + // The generalized template dispatches to is_tag_impl because + // is_tag and is_tag are equally specialized. + // This technique simulates making is_tag more-specialized. + template + struct is_tag + : is_tag_impl + {}; + +# define BOOST_ITERATOR_DERIVED_TAG1(base, derived) \ + BOOST_ITERATOR_DERIVED_TAG1_AUX(base, _, derived) + +# define BOOST_ITERATOR_DERIVED_TAG1_AUX(base, underscore, derived) \ + template \ + struct is_tag_impl \ + : is_tag \ + { \ + }; + + // Old-style tag relations + template + struct is_tag_impl + : mpl::or_< + is_tag + , is_tag + > + { + }; + + BOOST_ITERATOR_DERIVED_TAG1(std::output_iterator, detail::input_output_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::input_iterator, detail::input_output_iterator) + BOOST_ITERATOR_DERIVED_TAG1(detail::input_output_iterator, std::forward_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::forward_iterator, std::bidirectional_iterator) + BOOST_ITERATOR_DERIVED_TAG1(std::bidirectional_iterator, std::random_access_iterator) + + // Access tag relations + BOOST_ITERATOR_DERIVED_TAG1(readable_lvalue_iterator, writable_lvalue_iterator) + BOOST_ITERATOR_DERIVED_TAG1(swappable_iterator, readable_writable_iterator) + BOOST_ITERATOR_DERIVED_TAG1(readable_writable_iterator, writable_lvalue_iterator) + + template + struct is_tag_impl + : mpl::or_< + is_tag + , is_tag + > + { + }; + + BOOST_ITERATOR_DERIVED_TAG1(writable_iterator, readable_writable_iterator) + + // Traversal tag relations + BOOST_ITERATOR_DERIVED_TAG1(bidirectional_traversal, random_access_traversal) + BOOST_ITERATOR_DERIVED_TAG1(forward_traversal, bidirectional_traversal) + BOOST_ITERATOR_DERIVED_TAG1(single_pass_iterator, forward_traversal) + BOOST_ITERATOR_DERIVED_TAG1(incrementable_iterator, single_pass_iterator) + +# endif // BOOST_NO_IS_CONVERTIBLE workarounds + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION case + + +#endif + + // // Returns the minimum category type or error_type // if T1 and T2 are unrelated. @@ -446,19 +280,18 @@ namespace boost { // // template - struct minimum_category : -#ifndef BOOST_NO_IS_CONVERTIBLE - mpl::if_< is_base_or_same< T1, T2 >, - T1, - mpl::if_< is_base_or_same< T2, T1 >, - T2, - error_type > > -#else - minimum_category_select< minimum_return_category, - minimum_traversal_category > -#endif + struct minimum_category + : mpl::apply_if< + is_tag + , mpl::identity + , mpl::if_< + is_tag + , T2 + , error_type + > + > {}; - + } // namespace detail } // namespace boost diff --git a/include/boost/iterator/detail/enable_if.hpp b/include/boost/iterator/detail/enable_if.hpp index 7b22b90..d939fbb 100644 --- a/include/boost/iterator/detail/enable_if.hpp +++ b/include/boost/iterator/detail/enable_if.hpp @@ -69,7 +69,7 @@ namespace boost class Return> struct enable_if # if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) - : enabled::template base + : enabled<(Cond::value)>::template base # else : mpl::identity # endif diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp index 67a636b..8e21981 100644 --- a/include/boost/iterator/filter_iterator.hpp +++ b/include/boost/iterator/filter_iterator.hpp @@ -15,20 +15,18 @@ namespace boost { - - namespace detail { - + namespace detail + { template - struct filter_iterator_traits - : iterator_traits + struct filter_iterator_category { - typedef iterator_tag< - typename return_category::type - , typename minimum_category< - forward_traversal_tag - , typename traversal_category::type - >::type - > iterator_category; + typedef iterator_tag< + typename access_category::type + , typename minimum_category< + forward_traversal_tag + , typename traversal_category::type + >::type + > type; }; } // namespace detail @@ -37,13 +35,15 @@ namespace boost class filter_iterator : public iterator_adaptor< filter_iterator, Iterator - , detail::filter_iterator_traits + , not_specified + , typename detail::filter_iterator_category::type > { typedef iterator_adaptor< - filter_iterator, Iterator - , detail::filter_iterator_traits - > super_t; + filter_iterator, Iterator + , not_specified + , typename detail::filter_iterator_category::type + > super_t; friend class iterator_core_access; diff --git a/include/boost/iterator/indirect_iterator.hpp b/include/boost/iterator/indirect_iterator.hpp index 6c039fa..58d0143 100644 --- a/include/boost/iterator/indirect_iterator.hpp +++ b/include/boost/iterator/indirect_iterator.hpp @@ -13,6 +13,10 @@ #include #include +#include + +#include +#include #ifdef BOOST_NO_MPL_AUX_HAS_XXX # include @@ -23,6 +27,8 @@ namespace boost { + template + struct indirect_iterator; namespace detail { @@ -73,59 +79,103 @@ namespace boost // Metafunction returning the nested element_type typedef template - struct smart_pointer_traits - { - typedef typename remove_const< - typename T::element_type - >::type value_type; + struct smart_pointer_value : remove_const + {}; - typedef typename T::element_type& reference; - typedef typename T::element_type* pointer; + template + struct iterator_is_mutable + : mpl::not_< + boost::python::detail::is_reference_to_const< + typename iterator_reference::type + > + > + { }; + template + struct not_int_impl + { + template + struct apply { + typedef T type; + }; + }; + + template <> + struct not_int_impl {}; + + template + struct not_int + : not_int_impl::template apply {}; + // If the Value parameter is unspecified, we use this metafunction // to deduce the default types - template - struct indirect_defaults - : mpl::if_< - mpl::and_< - is_class::value_type> - , has_element_type::value_type> - > - , smart_pointer_traits::value_type> - , iterator_traits::value_type> - >::type + template + struct indirect_base { - typedef typename iterator_traits::iterator_category iterator_category; - typedef typename iterator_traits::difference_type difference_type; + typedef typename iterator_value::type dereferenceable; + + typedef mpl::and_< + is_class + , has_element_type + > is_smart_ptr; + + typedef typename mpl::apply_if< + is_smart_ptr + , smart_pointer_value + , iterator_value + >::type value_type; + + typedef typename mpl::if_< + mpl::or_< + is_smart_ptr + , iterator_is_mutable + > + , value_type + , value_type const + >::type cv_value_type; + + typedef iterator_adaptor< + indirect_iterator + , Iter + , cv_value_type + , Category + , Reference + , Pointer + , Difference + > type; }; - // The traits to use for indirect iterator, by default. Whatever - // is supplied gets passed through traits_iterator<...> so that it - // is ultimately derived from boost::iterator<...> - template - struct indirect_traits - : mpl::if_< - is_same - , indirect_defaults - , Traits - >::type - { - }; + template <> + struct indirect_base {}; } // namespace detail - template - class indirect_iterator : - public iterator_adaptor< - indirect_iterator - , Iterator - , detail::indirect_traits > + template < + class Iterator + , class Value = not_specified + , class Category = not_specified + , class Reference = not_specified + , class Pointer = not_specified + , class Difference = not_specified + > + class indirect_iterator + : public detail::indirect_base< + Iterator + , Value + , Category + , Reference + , Pointer + , Difference + >::type { - typedef iterator_adaptor< - indirect_iterator - , Iterator - , detail::indirect_traits - > super_t; + typedef typename detail::indirect_base< + Iterator + , Value + , Category + , Reference + , Pointer + , Difference + >::type super_t; friend class iterator_core_access; @@ -145,7 +195,14 @@ namespace boost {} private: - typename super_t::reference dereference() const { return **this->base(); } + typename super_t::reference dereference() const + { +# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + return const_cast(**this->base()); +# else + return **this->base(); +# endif + } }; diff --git a/include/boost/iterator/iterator_adaptor.hpp b/include/boost/iterator/iterator_adaptor.hpp index 2d47c71..3508adb 100644 --- a/include/boost/iterator/iterator_adaptor.hpp +++ b/include/boost/iterator/iterator_adaptor.hpp @@ -17,16 +17,20 @@ #include #include +#include #include +#include + #include #include #include +#include + namespace boost { - namespace detail { template @@ -37,8 +41,8 @@ namespace boost , typename Other::iterator_category > , is_same< - typename Traits::iterator_category - , typename Other::iterator_category + typename Traits::iterator_category // *** THIS IS A BUG!! *** + , typename Other::iterator_category // MAKE FAILING TEST BEFORE FIXING!! > > {}; @@ -116,6 +120,7 @@ namespace boost # endif }; + // // iterator_traits_adaptor can be used to create new iterator traits by adapting // the traits of a given iterator type. Together with iterator_adaptor it simplifies @@ -123,68 +128,125 @@ namespace boost // argument ordering is different from the std::iterator template, so that default // arguments can be used effectivly. // - template < - class Iterator - , class ValueType = typename detail::iterator_traits::value_type - , class Reference = ValueType& - , class Pointer = ValueType* - , class IteratorCategory = typename detail::iterator_traits::iterator_category - , class DifferenceType = typename detail::iterator_traits::difference_type - > - struct iterator_traits_adaptor - : iterator< - IteratorCategory - , ValueType - , DifferenceType - , Pointer - , Reference - > + // The ordering changed slightly with respect to former versions of iterator_adaptor + // The idea is that when the user needs to fiddle with the reference type + // it is highly likely that the iterator category has to be adjusted as well + // + // Value - if supplied, the value_type of the resulting iterator, unless + // const. If const, a conforming compiler strips constness for the + // value_type. If not supplied, iterator_traits::value_type is used + // + // Reference - the reference type of the resulting iterator, and in + // particular, the result type of operator*(). If not supplied but + // Value is supplied, Value& is used. Otherwise + // iterator_traits::reference is used. + // + // Pointer - the pointer type of the resulting iterator, and in + // particular, the result type of operator->(). If not + // supplied but Value is supplied, Value* is used. Otherwise + // iterator_traits::pointer is used. + // + // Category - the iterator_category of the resulting iterator. If not + // supplied, iterator_traits::iterator_category is used. + // + // Distance - the difference_type of the resulting iterator. If not + // supplied, iterator_traits::difference_type is used. + // + // TODO + // ? Automatic adjustment of category ? + // + namespace detail { - }; + template + struct ia_dflt_help + : mpl::apply_if< + mpl::and_< + is_same + , Condition + > + , DefaultNullaryFn + , mpl::identity + > + { + }; + template < + class Derived + , class Base + , class Value + , class Category + , class Reference + , class Pointer + , class Difference + > + struct iterator_adaptor_base + { + typedef iterator_facade< + Derived + , typename detail::ia_dflt_help >::type + , typename detail::ia_dflt_help >::type + , typename detail::ia_dflt_help , iterator_reference >::type + , typename detail::ia_dflt_help , iterator_pointer >::type + , typename detail::ia_dflt_help >::type + > + type; + }; + + } + // // // template < class Derived - , class Iterator - , class Traits = detail::iterator_traits + , class Base + , class Value = not_specified + , class Category = not_specified + , class Reference = not_specified + , class Pointer = not_specified + , class Difference = not_specified > class iterator_adaptor - : public iterator_facade + : public detail::iterator_adaptor_base< + Derived, Base, Value, Category, Reference, Pointer, Difference + >::type { friend class iterator_core_access; + typedef typename detail::iterator_adaptor_base< + Derived, Base, Value, Category, Reference, Pointer, Difference + >::type super_t; + public: iterator_adaptor() {} - explicit iterator_adaptor(Iterator iter) + explicit iterator_adaptor(Base iter) : m_iterator(iter) { } - Iterator base() const + Base base() const { return m_iterator; } protected: // Core iterator interface for iterator_facade // - typename Traits::reference dereference() const + typename super_t::reference dereference() const { return *m_iterator; } template < - class OtherDerived, class OtherIterator, class OtherTraits + class OtherDerived, class OtherIterator, class V, class C, class R, class P, class D > - bool equal(iterator_adaptor const& x) const + bool equal(iterator_adaptor const& x) const { BOOST_STATIC_ASSERT( - (detail::same_category_and_difference::value) + (detail::same_category_and_difference::value) ); return m_iterator == x.base(); } - void advance(typename Traits::difference_type n) + void advance(typename super_t::difference_type n) { m_iterator += n; } @@ -192,19 +254,24 @@ namespace boost void increment() { ++m_iterator; } void decrement() { --m_iterator; } - template - typename Traits::difference_type distance_to( - iterator_adaptor const& y) const + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class P, class D + > + typename super_t::difference_type distance_to( + iterator_adaptor const& y) const { BOOST_STATIC_ASSERT( - (detail::same_category_and_difference::value) + (detail::same_category_and_difference::value) ); return y.base() - m_iterator; } - private: // data members - Iterator m_iterator; + // Needed for counting iterator + Base const& base_reference() const + { return m_iterator; } + private: // data members + Base m_iterator; }; } // namespace boost diff --git a/include/boost/iterator/iterator_categories.hpp b/include/boost/iterator/iterator_categories.hpp index c9a43de..fd96d21 100644 --- a/include/boost/iterator/iterator_categories.hpp +++ b/include/boost/iterator/iterator_categories.hpp @@ -12,17 +12,23 @@ #include #include + #include #include + +#include + #include #include + #include #include #include #include #include #include -#include +#include + #include #if BOOST_WORKAROUND(__MWERKS__, <=0x2407) @@ -33,60 +39,142 @@ namespace boost { namespace detail { - - template - struct choose_lvalue_return - : mpl::if_< - is_const - , boost::constant_lvalue_iterator_tag - , boost::mutable_lvalue_iterator_tag> - { - }; - - - template - struct iter_category_to_return - : mpl::if_< - is_forward_iterator - , typename choose_lvalue_return::type - , typename mpl::if_< - is_input_iterator - , boost::readable_iterator_tag - , typename mpl::if_< - is_output_iterator - , boost::writable_iterator_tag - , boost::error_iterator_tag - >::type - >::type - > + // Helper metafunction for std_category below + template + struct match_tag + : mpl::apply_if, mpl::identity, Next> { }; - template - struct iter_category_to_traversal - : mpl::if_< - is_random_access_iterator - , random_access_traversal_tag - , typename mpl::if_< - is_bidirectional_iterator - , bidirectional_traversal_tag - , typename mpl::if_< - is_forward_iterator - , forward_traversal_tag - , typename mpl::if_< - is_input_iterator - , input_traversal_tag - , output_traversal_tag - >::type - >::type - >::type + // Converts a possibly user-defined category tag to the + // most-derived standard tag which is a base of that tag. + template + struct std_category + : match_tag< + Category, std::random_access_iterator_tag + , match_tag +# else + , void +# endif + > + > + > + > > { }; + // std_to_new_tags -- + // + // A metafunction which converts any standard tag into its + // corresponding new-style traversal tag. + // + // Also, instantiations are metafunction classes which convert a + // reference type into a corresponding new-style access tag. + template struct std_to_new_tags +# if BOOST_WORKAROUND(BOOST_MSVC, == 1300) // handle ETI + { + typedef void type; + template struct apply { typedef void type; }; + } +# endif + ; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // handle ETI + template <> struct std_to_new_tags {}; +# endif + + // + // Specializations for specific standard tags + // + template <> + struct std_to_new_tags + { + typedef single_pass_iterator_tag type; + + template + struct apply + : mpl::identity {}; + + }; + + template <> + struct std_to_new_tags + { + typedef incrementable_iterator_tag type; + + template + struct apply + : mpl::identity {}; + }; + + template <> + struct std_to_new_tags + { + typedef forward_traversal_tag type; + + template + struct apply + : mpl::if_< + python::detail::is_reference_to_const + , boost::readable_lvalue_iterator_tag + , boost::writable_lvalue_iterator_tag + > + {}; + }; + + template <> + struct std_to_new_tags + : std_to_new_tags + { + typedef bidirectional_traversal_tag type; + }; + + template <> + struct std_to_new_tags + : std_to_new_tags + { + typedef random_access_traversal_tag type; + }; + + template + struct old_tag_converter + : std_to_new_tags< + typename std_category::type + > + { + }; + + template + struct iter_category_to_traversal + : std_to_new_tags< + typename std_category::type + > + {}; + + template + struct iter_category_to_access + : mpl::apply1< + iter_category_to_traversal + , Reference + > + {}; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + // Deal with ETI + template <> struct iter_category_to_access {}; + template <> struct iter_category_to_traversal {}; +# endif + + // A metafunction returning true iff T is boost::iterator_tag template struct is_boost_iterator_tag; - + #if BOOST_WORKAROUND(__MWERKS__, <= 0x2407) // // has_xxx fails, so we have to use @@ -98,9 +186,13 @@ namespace boost { // defined for cwpro7. // template - struct is_new_iterator_tag : - mpl::and_< mpl::not_< is_input_iterator >, - mpl::not_< is_output_iterator > > + struct is_new_iterator_tag + : mpl::not_< + mpl::or_< + is_tag + , is_tag + > + > {}; #elif BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \ @@ -118,12 +210,11 @@ namespace boost { template struct is_new_iterator_tag - : //has_traversal - mpl::if_< - is_class - , has_traversal - , mpl::false_ - >::type + : mpl::if_< + is_class + , has_traversal + , mpl::false_ + >::type { }; @@ -134,7 +225,7 @@ namespace boost { namespace detail { template - struct get_return_category { + struct get_access_category { typedef typename NewCategoryTag::returns type; }; template @@ -142,51 +233,57 @@ namespace boost { typedef typename NewCategoryTag::traversal type; }; - template - struct return_category_tag + template + struct access_category_tag : mpl::apply_if< - is_new_iterator_tag - , get_return_category - , iter_category_to_return + is_new_iterator_tag + , get_access_category + , iter_category_to_access > { }; - template + template struct traversal_category_tag - : mpl::apply_if< - is_new_iterator_tag - , get_traversal_category - , iter_category_to_traversal - > + : mpl::apply_if< + is_new_iterator_tag + , get_traversal_category + , iter_category_to_traversal + > { }; +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + // Deal with ETI + template <> struct access_category_tag {}; + template <> struct traversal_category_tag {}; +# endif + } // namespace detail template - struct return_category - : detail::return_category_tag< + struct access_category + : detail::access_category_tag< typename detail::iterator_traits::iterator_category - , typename detail::iterator_traits::value_type> + , typename detail::iterator_traits::reference> {}; template struct traversal_category - : detail::traversal_category_tag< + : detail::traversal_category_tag< typename detail::iterator_traits::iterator_category - , typename detail::iterator_traits::value_type> + > { }; #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) template - struct return_category + struct access_category : mpl::if_< is_const - , constant_lvalue_iterator_tag - , mutable_lvalue_iterator_tag> + , readable_lvalue_iterator_tag + , writable_lvalue_iterator_tag> { }; @@ -198,50 +295,12 @@ namespace boost { #endif - // TODO Fix this for BOOST_NO_IS_CONVERTIBLE - - template - struct cvt_iterator_category - : mpl::if_< - mpl::or_< - detail::is_mutable_lvalue_iterator - , detail::is_constant_lvalue_iterator - > - , typename mpl::if_< - detail::is_random_access_traversal_iterator - , std::random_access_iterator_tag - , typename mpl::if_< - detail::is_bidirectional_traversal_iterator - , std::bidirectional_iterator_tag - , typename mpl::if_< - detail::is_forward_traversal_iterator - , std::forward_iterator_tag - , error_iterator_tag - >::type - >::type - >::type - - , typename mpl::if_< - mpl::and_< - detail::is_readable_iterator - , detail::is_input_traversal_iterator - > - , std::input_iterator_tag - , typename mpl::if_< - mpl::and_< - detail::is_writable_iterator - , detail::is_output_traversal_iterator - > - , std::output_iterator_tag - , error_iterator_tag - >::type - >::type - > - { - }; - template - struct iterator_tag : cvt_iterator_category::type + struct iterator_tag + : detail::minimum_category< + typename ReturnTag::max_category + , typename TraversalTag::max_category + > { typedef ReturnTag returns; typedef TraversalTag traversal; @@ -264,11 +323,11 @@ namespace boost { typedef char (&yes)[1]; typedef char (&no)[2]; - template - static yes test(iterator_tag const&); + template + static yes test(mpl::identity >*); static no test(...); - static T inst; + static mpl::identity* inst; BOOST_STATIC_CONSTANT(bool, value = sizeof(test(inst)) == sizeof(yes)); typedef mpl::bool_ type; }; diff --git a/include/boost/iterator/iterator_concepts.hpp b/include/boost/iterator/iterator_concepts.hpp index b39b722..f7c67ce 100644 --- a/include/boost/iterator/iterator_concepts.hpp +++ b/include/boost/iterator/iterator_concepts.hpp @@ -43,9 +43,9 @@ namespace boost_concepts { template class ReadableIteratorConcept { public: - typedef typename boost::detail::iterator_traits::value_type value_type; - typedef typename boost::detail::iterator_traits::reference reference; - typedef typename boost::return_category::type return_category; + typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME ::boost::detail::iterator_traits::reference reference; + typedef BOOST_DEDUCED_TYPENAME ::boost::access_category::type access_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); @@ -53,7 +53,7 @@ namespace boost_concepts { boost::function_requires< boost::DefaultConstructibleConcept >(); - static_assert_base_and_derived(); + static_assert_base_and_derived(); reference r = *i; // or perhaps read(x) value_type v(r); @@ -65,7 +65,7 @@ namespace boost_concepts { template class WritableIteratorConcept { public: - typedef typename boost::return_category::type return_category; + typedef typename boost::access_category::type access_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); @@ -73,7 +73,7 @@ namespace boost_concepts { boost::function_requires< boost::DefaultConstructibleConcept >(); - static_assert_base_and_derived(); + static_assert_base_and_derived(); *i = v; // a good alternative could be something like write(x, v) } @@ -86,12 +86,12 @@ namespace boost_concepts { public: typedef typename boost::detail::iterator_traits::value_type value_type; typedef typename boost::detail::iterator_traits::reference reference; - typedef typename boost::return_category::type return_category; + typedef typename boost::access_category::type access_category; void constraints() { boost::function_requires< ReadableIteratorConcept >(); - static_assert_base_and_derived(); + static_assert_base_and_derived(); BOOST_STATIC_ASSERT((boost::is_same::value)); @@ -106,14 +106,14 @@ namespace boost_concepts { public: typedef typename boost::detail::iterator_traits::value_type value_type; typedef typename boost::detail::iterator_traits::reference reference; - typedef typename boost::return_category::type return_category; + typedef typename boost::access_category::type access_category; void constraints() { boost::function_requires< ReadableIteratorConcept >(); boost::function_requires< WritableIteratorConcept >(); - static_assert_base_and_derived(); + static_assert_base_and_derived(); BOOST_STATIC_ASSERT((boost::is_same::value)); @@ -188,54 +188,56 @@ namespace boost_concepts { //=========================================================================== // Iterator Interoperability Concept - namespace detail { +namespace detail +{ - template - struct Operations; + template + struct Operations; - template <> - struct Operations - { + template <> + struct Operations + { template static void constraints(Iterator1 const& i1, Iterator2 const& i2) { - i1 == i2; - i1 != i2; - - i2 == i1; - i2 != i1; + // no interoperability constraints } - }; + }; - template <> - struct Operations - { + template <> + struct Operations + { template static void constraints(Iterator1 const& i1, Iterator2 const& i2) { - Operations::constraints(i1, i2); - } - }; + Operations(i1, i2); + i1 == i2; + i1 != i2; - template <> - struct Operations - { + i2 == i1; + i2 != i1; + } + }; + + template <> + struct Operations + { template static void constraints(Iterator1 const& i1, Iterator2 const& i2) { - Operations::constraints(i1, i2); + Operations::constraints(i1, i2); } - }; + }; - template <> - struct Operations - { + template <> + struct Operations + { template static void constraints(Iterator1 const& i1, Iterator2 const& i2) { - Operations::constraints(i1, i2); + Operations::constraints(i1, i2); } - }; + }; template <> struct Operations diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index c8bb8e3..018a35d 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -10,18 +10,25 @@ #define BOOST_ITERATOR_FACADE_23022003THW_HPP #include + #include +#include #include #include #include #include +#include #include +#include + namespace boost { + struct not_specified; + namespace detail { @@ -53,19 +60,135 @@ namespace boost // Generates the corresponding std::iterator specialization // from the given iterator traits type // - template - struct std_iterator_from_traits - : iterator< - typename Traits::iterator_category - , typename Traits::value_type - , typename Traits::difference_type - , typename Traits::pointer - , typename Traits::reference - > + template + struct iterator_facade_base { + typedef iterator< + Category + + , typename remove_cv::type + + , Difference + + , typename mpl::if_< + is_same + , Value* + , Pointer + >::type + + , typename mpl::if_< + is_same + , Value& + , Reference + >::type + > + type; }; + // operator->() needs special support for input iterators to strictly meet the + // standard's requirements. If *i is not a reference type, we must still + // produce a (constant) lvalue to which a pointer can be formed. We do that by + // returning an instantiation of this special proxy class template. + + template + struct operator_arrow_proxy + { + operator_arrow_proxy(const T& x) : m_value(x) {} + const T* operator->() const { return &m_value; } + // This function is needed for MWCW and BCC, which won't call operator-> + // again automatically per 13.3.1.2 para 8 + operator const T*() const { return &m_value; } + T m_value; + }; + + template + struct operator_arrow_pointer + { + operator_arrow_pointer(Reference x) : m_p(&x) {} + operator Pointer() const { return m_p; } + Pointer m_p; + }; + + template + struct operator_arrow_result + : mpl::if_< + is_tag< + readable_lvalue_iterator_tag + , typename access_category_tag::type + > + , operator_arrow_proxy + , Pointer + > + { + }; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) + // Deal with ETI + template<> + struct operator_arrow_result + { + typedef int type; + }; +# endif + + // + // Facade is actually an iterator. We require Facade here + // so that we do not have to go through iterator_traits + // to access the traits + // + template + class index_operator_proxy + { + typedef typename Iterator::reference reference; + typedef typename Iterator::value_type value_type; + + public: + index_operator_proxy(Iterator const& iter) + : m_iter(iter) + {} + + operator reference() + { + return *m_iter; + } + + index_operator_proxy& operator=(value_type const& val) + { + *m_iter = val; + return *this; + } + + private: + Iterator m_iter; + }; + + template + struct index_operator_result + { + typedef typename access_category_tag::type access_category; + + typedef is_tag use_proxy; + + typedef typename mpl::if_< + use_proxy + , index_operator_proxy + , ValueType + >::type type; + }; + + template + index_operator_proxy make_index_operator_result(Iterator const& iter, mpl::true_) + { + return index_operator_proxy(iter); + } + + template + typename Iterator::value_type make_index_operator_result(Iterator const& iter, mpl::false_) + { + return *iter; + } + } // namespace detail @@ -131,17 +254,24 @@ namespace boost // template < class Derived - , class Traits + , class Value = not_specified + , class Category = not_specified + , class Reference = not_specified + , class Pointer = not_specified + , class Difference = not_specified > class iterator_facade - : public detail::std_iterator_from_traits + : public detail::iterator_facade_base::type { - typedef detail::std_iterator_from_traits super_t; + private: + typedef iterator_facade self_t; + + typedef typename + detail::iterator_facade_base::type + super_t; - public: // - // CRT interface. There is no simple way to remove this - // from the public interface without template friends + // CRT interface. // typedef Derived derived_t; @@ -155,10 +285,13 @@ namespace boost return static_cast(*this); } + public: + typedef typename super_t::value_type value_type; typedef typename super_t::reference reference; typedef typename super_t::difference_type difference_type; typedef typename super_t::pointer pointer; + typedef typename super_t::iterator_category iterator_category; reference operator*() const { @@ -166,14 +299,32 @@ namespace boost } // Needs eventual help for input iterators - pointer operator->() const + typename detail::operator_arrow_result< + value_type + , iterator_category + , reference + , pointer + >::type + operator->() const { - return &iterator_core_access::dereference(this->derived()); + typedef typename detail::operator_arrow_result< + value_type + , iterator_category + , reference + , detail::operator_arrow_pointer + >::type result_t; + + return result_t(*this->derived()); } - reference operator[](difference_type n) const + typename detail::index_operator_result::type + operator[](difference_type n) const { - return *(*this + n); + typedef typename + detail::index_operator_result::use_proxy + use_proxy; + + return detail::make_index_operator_result(this->derived() + n, use_proxy()); } Derived& operator++() @@ -289,13 +440,16 @@ namespace boost // # define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, condition, return_prefix, base_op) \ - template \ + template < \ + class Derived1, class V1, class C1, class R1, class P1, class D1 \ + , class Derived2, class V2, class C2, class R2, class P2, class D2 \ + > \ inline typename detail::enable_if_interoperable< \ Derived1, Derived2, result_type \ >::type \ operator op( \ - iterator_facade const& lhs \ - , iterator_facade const& rhs) \ + iterator_facade const& lhs \ + , iterator_facade const& rhs) \ { \ /* For those compilers that do not support enable_if */ \ BOOST_STATIC_ASSERT(( \ @@ -303,8 +457,8 @@ namespace boost && condition \ )); \ return_prefix iterator_core_access::base_op( \ - rhs.derived(), lhs.derived()); \ - } + static_cast(rhs), static_cast(lhs)); \ + } # define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \ BOOST_ITERATOR_FACADE_INTEROP( \ @@ -327,31 +481,31 @@ namespace boost // operator- requires an additional part in the static assertion BOOST_ITERATOR_FACADE_INTEROP( - - , typename Traits1::difference_type + , typename Derived1::difference_type , (is_same< - BOOST_ARG_DEP_TYPENAME Traits1::difference_type - , BOOST_ARG_DEP_TYPENAME Traits2::difference_type + BOOST_ARG_DEP_TYPENAME Derived1::difference_type + , BOOST_ARG_DEP_TYPENAME Derived2::difference_type >::value) , return , distance_to ) # undef BOOST_ITERATOR_FACADE_INTEROP -# define BOOST_ITERATOR_FACADE_PLUS(args) \ - template \ - inline Derived operator+ args \ - { \ - Derived tmp(i.derived()); \ - return tmp += n; \ +# define BOOST_ITERATOR_FACADE_PLUS(args) \ + template \ + inline Derived operator+ args \ + { \ + Derived tmp(static_cast(i)); \ + return tmp += n; \ } BOOST_ITERATOR_FACADE_PLUS(( - iterator_facade const& i - , typename Traits::difference_type n + iterator_facade const& i + , typename Derived::difference_type n )) BOOST_ITERATOR_FACADE_PLUS(( - typename Traits::difference_type n - , iterator_facade const& i + typename Derived::difference_type n + , iterator_facade const& i )) # undef BOOST_ITERATOR_FACADE_PLUS diff --git a/include/boost/iterator/iterator_traits.hpp b/include/boost/iterator/iterator_traits.hpp new file mode 100755 index 0000000..4f0d46f --- /dev/null +++ b/include/boost/iterator/iterator_traits.hpp @@ -0,0 +1,93 @@ +// Copyright David Abrahams 2003. 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. +#ifndef ITERATOR_TRAITS_DWA200347_HPP +# define ITERATOR_TRAITS_DWA200347_HPP + +# include +# include + +namespace boost { + +// Unfortunately, g++ 2.95.x chokes when we define a class template +// iterator_category which has the same name as its +// std::iterator_category() function, probably due in part to the +// "std:: is visible globally" hack it uses. Use +// BOOST_ITERATOR_CATEGORY to write code that's portable to older +// GCCs. + +# if BOOST_WORKAROUND(__GNUC__, <= 2) +# define BOOST_ITERATOR_CATEGORY iterator_category_ +# else +# define BOOST_ITERATOR_CATEGORY iterator_category +# endif + + +template +struct iterator_value +{ + typedef typename detail::iterator_traits::value_type type; +}; + +template +struct iterator_reference +{ + typedef typename detail::iterator_traits::reference type; +}; + + +template +struct iterator_pointer +{ + typedef typename detail::iterator_traits::pointer type; +}; + +template +struct iterator_difference +{ + typedef typename detail::iterator_traits::difference_type type; +}; + +template +struct BOOST_ITERATOR_CATEGORY +{ + typedef typename detail::iterator_traits::iterator_category type; +}; + +# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) +template <> +struct iterator_value +{ + typedef void type; +}; + +template <> +struct iterator_reference +{ + typedef void type; +}; + +template <> +struct iterator_pointer +{ + typedef void type; +}; + +template <> +struct iterator_difference +{ + typedef void type; +}; + +template <> +struct BOOST_ITERATOR_CATEGORY +{ + typedef void type; +}; +# endif + +} // namespace boost::iterator + +#endif // ITERATOR_TRAITS_DWA200347_HPP diff --git a/include/boost/iterator/new_iterator_tests.hpp b/include/boost/iterator/new_iterator_tests.hpp index ef609e7..9814d2a 100644 --- a/include/boost/iterator/new_iterator_tests.hpp +++ b/include/boost/iterator/new_iterator_tests.hpp @@ -30,8 +30,8 @@ namespace boost { void is_readable(readable_iterator_tag) { } void is_writable(writable_iterator_tag) { } void is_swappable(swappable_iterator_tag) { } -void is_constant_lvalue(constant_lvalue_iterator_tag) { } -void is_mutable_lvalue(mutable_lvalue_iterator_tag) { } +void is_constant_lvalue(readable_lvalue_iterator_tag) { } +void is_mutable_lvalue(writable_lvalue_iterator_tag) { } // Preconditions: *i == v template @@ -45,7 +45,7 @@ void readable_iterator_test(const Iterator i1, T v) T v2 = r2; assert(v1 == v); assert(v2 == v); - typename return_category::type result_category; + typename access_category::type result_category; is_readable(result_category); } @@ -54,7 +54,7 @@ void writable_iterator_test(Iterator i, T v) { Iterator i2(i); // Copy Constructible *i2 = v; - is_writable(typename return_category::type()); + is_writable(typename access_category::type()); } template @@ -65,7 +65,7 @@ void swappable_iterator_test(Iterator i, Iterator j) iter_swap(i2, j2); typename detail::iterator_traits::value_type ai = *i, aj = *j; assert(bi == aj && bj == ai); - typedef typename return_category::type result_category; + typedef typename access_category::type result_category; is_swappable(result_category()); } @@ -78,7 +78,7 @@ void constant_lvalue_iterator_test(Iterator i, T v1) BOOST_STATIC_ASSERT((is_same::value)); const T& v2 = *i2; assert(v1 == v2); - typedef typename return_category::type result_category; + typedef typename access_category::type result_category; is_constant_lvalue(result_category()); } @@ -94,7 +94,7 @@ void mutable_lvalue_iterator_test(Iterator i, T v1, T v2) *i = v2; T& v4 = *i2; assert(v2 == v4); - typedef typename return_category::type result_category; + typedef typename access_category::type result_category; is_mutable_lvalue(result_category()); } diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index 052cf6a..8b0d0c9 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -15,43 +15,36 @@ namespace boost { + template + class transform_iterator; namespace detail { - // Given the transform iterator's transformation and iterator, this // is the type used as its traits. template - struct transform_iterator_traits - : iterator_traits_adaptor< - Iterator + struct transform_iterator_base + { + typedef iterator_adaptor< + transform_iterator + , Iterator , typename AdaptableUnaryFunction::result_type - , typename AdaptableUnaryFunction::result_type - , typename AdaptableUnaryFunction::result_type* , iterator_tag< readable_iterator_tag , typename traversal_category::type > - > - { + , typename AdaptableUnaryFunction::result_type + > type; }; + } - } // transform_iterator_traits - - // template class transform_iterator - : public iterator_adaptor< - transform_iterator - , Iterator - , detail::transform_iterator_traits - > + : public detail::transform_iterator_base::type { - typedef iterator_adaptor< - transform_iterator - , Iterator - , detail::transform_iterator_traits - > super_t; + typedef typename + detail::transform_iterator_base::type + super_t; friend class iterator_core_access; diff --git a/test/Jamfile b/test/Jamfile index 6c0b480..ed1a5fd 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -2,6 +2,7 @@ SEARCH on testing.jam = $(BOOST_BUILD_PATH) ; include testing.jam ; run concept_tests.cpp ; run iterator_adaptor_cc.cpp ; +run counting_iterator_test.cpp ; run transform_iterator_test.cpp ; run indirect_iterator_test.cpp ; run filter_iterator_test.cpp ; diff --git a/test/concept_tests.cpp b/test/concept_tests.cpp index e3a2ef2..3ffcdb0 100644 --- a/test/concept_tests.cpp +++ b/test/concept_tests.cpp @@ -10,7 +10,7 @@ struct new_iterator : public boost::iterator< boost::iterator_tag< - boost::mutable_lvalue_iterator_tag + boost::writable_lvalue_iterator_tag , boost::random_access_traversal_tag>, int> { int& operator*() const { return *m_x; } @@ -53,16 +53,14 @@ old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; } int main() { - BOOST_STATIC_ASSERT( boost::detail::is_random_access_traversal_iterator::value ); - - typedef boost::iterator_tag< boost::mutable_lvalue_iterator_tag, boost::random_access_traversal_tag > tag; + typedef boost::iterator_tag< boost::writable_lvalue_iterator_tag, boost::random_access_traversal_tag > tag; // BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); BOOST_STATIC_ASSERT((boost::is_same::value)); // BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); BOOST_STATIC_ASSERT((boost::is_same::value)); typedef boost::traversal_category::type traversal_category; diff --git a/test/counting_iterator_test.cpp b/test/counting_iterator_test.cpp new file mode 100755 index 0000000..fbfe70b --- /dev/null +++ b/test/counting_iterator_test.cpp @@ -0,0 +1,295 @@ +// (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. +// +// See http://www.boost.org for most recent version including documentation. +// +// Revision History +// 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with +// plain MSVC again. (David Abrahams) +// 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in +// MSVC without STLport, so that the other tests may proceed +// (David Abrahams) +// 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams) +// 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams) +// 24 Jan 2001 Initial revision (David Abrahams) + +#include + +#ifdef __BORLANDC__ // Borland mis-detects our custom iterators +# pragma warn -8091 // template argument ForwardIterator passed to '...' is a output iterator +# pragma warn -8071 // Conversion may lose significant digits (due to counting_iterator += n). +#endif + +#ifdef BOOST_MSVC +# pragma warning(disable:4786) // identifier truncated in debug info +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#ifndef __BORLANDC__ +# include +#endif +#include +#include +#include +#ifndef BOOST_NO_SLIST +# include +#endif + + +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +template +struct signed_assert_nonnegative +{ + static void test(T x) { assert(x >= 0); } +}; + +template +struct unsigned_assert_nonnegative +{ + static void test(T x) {} +}; + +template +struct assert_nonnegative + : boost::mpl::if_c< + std::numeric_limits::is_signed + , signed_assert_nonnegative + , unsigned_assert_nonnegative + >::type +{ +}; +#endif + +// Special tests for RandomAccess CountingIterators. +template +void category_test( + CountingIterator start, + CountingIterator finish, + Value, + std::random_access_iterator_tag) +{ + typedef typename + boost::detail::iterator_traits::difference_type + difference_type; + difference_type distance = boost::detail::distance(start, finish); + + // Pick a random position internal to the range + difference_type offset = (unsigned)rand() % distance; + +#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + assert(offset >= 0); +#else + assert_nonnegative::test(offset); +#endif + + CountingIterator internal = start; + std::advance(internal, offset); + + // Try some binary searches on the range to show that it's ordered + assert(std::binary_search(start, finish, *internal)); + + // #including tuple crashed borland, so I had to give up on tie(). + std::pair xy( + std::equal_range(start, finish, *internal)); + CountingIterator x = xy.first, y = xy.second; + + assert(boost::detail::distance(x, y) == 1); + + // Show that values outside the range can't be found + assert(!std::binary_search(start, boost::prior(finish), *finish)); + + // Do the generic random_access_iterator_test + typedef typename CountingIterator::value_type value_type; + std::vector v; + for (value_type z = *start; !(z == *finish); ++z) + v.push_back(z); + + // Note that this test requires a that the first argument is + // dereferenceable /and/ a valid iterator prior to the first argument + boost::random_access_iterator_test(start, v.size(), v.begin()); +} + +// Special tests for bidirectional CountingIterators +template +void category_test(CountingIterator start, Value v1, std::bidirectional_iterator_tag) +{ + Value v2 = v1; + ++v2; + + // Note that this test requires a that the first argument is + // dereferenceable /and/ a valid iterator prior to the first argument + boost::bidirectional_iterator_test(start, v1, v2); +} + +template +void category_test(CountingIterator start, CountingIterator finish, Value v1, std::forward_iterator_tag) +{ + Value v2 = v1; + ++v2; + if (finish != start && finish != boost::next(start)) + boost::forward_readable_iterator_test(start, finish, v1, v2); +} + +template +void test_aux(CountingIterator start, CountingIterator finish, Value v1) +{ + typedef typename CountingIterator::iterator_category category; + typedef typename CountingIterator::value_type value_type; + + // If it's a RandomAccessIterator we can do a few delicate tests + category_test(start, finish, v1, category()); + + // Okay, brute force... + for (CountingIterator p = start + ; p != finish && boost::next(p) != finish + ; ++p) + { + assert(boost::next(*p) == *boost::next(p)); + } + + // prove that a reference can be formed to these values + typedef typename CountingIterator::value_type value; + const value* q = &*start; + (void)q; // suppress unused variable warning +} + +template +void test(Incrementable start, Incrementable finish) +{ + test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish), start); +} + +template +void test_integer(Integer* = 0) // default arg works around MSVC bug +{ + Integer start = 0; + Integer finish = 120; + test(start, finish); +} + +template +void test_integer3(Integer* = 0, Category* = 0, Difference* = 0) // default arg works around MSVC bug +{ + Integer start = 0; + Integer finish = 120; + typedef boost::counting_iterator iterator; + test_aux(iterator(start), iterator(finish), start); +} + +template +void test_container(Container* = 0) // default arg works around MSVC bug +{ + Container c(1 + (unsigned)rand() % 1673); + + const typename Container::iterator start = c.begin(); + + // back off by 1 to leave room for dereferenceable value at the end + typename Container::iterator finish = start; + std::advance(finish, c.size() - 1); + + test(start, finish); + + typedef typename Container::const_iterator const_iterator; + test(const_iterator(start), const_iterator(finish)); +} + +class my_int1 { +public: + my_int1() { } + my_int1(int x) : m_int(x) { } + my_int1& operator++() { ++m_int; return *this; } + bool operator==(const my_int1& x) const { return m_int == x.m_int; } +private: + int m_int; +}; + +class my_int2 { +public: + typedef void value_type; + typedef void pointer; + typedef void reference; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + my_int2() { } + my_int2(int x) : m_int(x) { } + my_int2& operator++() { ++m_int; return *this; } + my_int2& operator--() { --m_int; return *this; } + bool operator==(const my_int2& x) const { return m_int == x.m_int; } +private: + int m_int; +}; + +class my_int3 { +public: + typedef void value_type; + typedef void pointer; + typedef void reference; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + + my_int3() { } + my_int3(int x) : m_int(x) { } + my_int3& operator++() { ++m_int; return *this; } + my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; } + std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; } + my_int3& operator--() { --m_int; return *this; } + bool operator==(const my_int3& x) const { return m_int == x.m_int; } + bool operator!=(const my_int3& x) const { return m_int != x.m_int; } + bool operator<(const my_int3& x) const { return m_int < x.m_int; } +private: + int m_int; +}; + +int main() +{ + // Test the built-in integer types. + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); +#if defined(BOOST_HAS_LONG_LONG) + test_integer(); + test_integer(); +#endif + + // Test user-defined type. + + test_integer3(); + test_integer(); + test_integer(); + + // Some tests on container iterators, to prove we handle a few different categories + test_container >(); + test_container >(); +# ifndef BOOST_NO_SLIST + test_container >(); +# endif + + // Also prove that we can handle raw pointers. + int array[2000]; + test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1)); + + return 0; +} diff --git a/test/filter_iterator_test.cpp b/test/filter_iterator_test.cpp index ea34b6d..0cdad99 100644 --- a/test/filter_iterator_test.cpp +++ b/test/filter_iterator_test.cpp @@ -13,10 +13,12 @@ using boost::dummyT; -struct one_or_four { - bool operator()(dummyT x) const { - return x.foo() == 1 || x.foo() == 4; - } +struct one_or_four +{ + bool operator()(dummyT x) const + { + return x.foo() == 1 || x.foo() == 4; + } }; #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION @@ -27,6 +29,7 @@ namespace boost { namespace detail }} #endif +template struct undefined; // Test filter iterator int main() @@ -41,11 +44,15 @@ int main() filter_iter(one_or_four(), array, array+N) , dummyT(1), dummyT(4)); - //# if 0 - BOOST_STATIC_ASSERT( - (!boost::detail::is_bidirectional_traversal_iterator< - boost::traversal_category::type - >::value) ); + // Filter iterators can't be bidirectional, since we didn't choose + // to store the beginning of the range. + BOOST_STATIC_ASSERT(( + !boost::detail::is_tag< + boost::bidirectional_traversal_tag + , boost::traversal_category::type + >::value + )); + //# endif // On compilers not supporting partial specialization, we can do more type diff --git a/test/indirect_iterator_test.cpp b/test/indirect_iterator_test.cpp index 1708e1e..43fa4ae 100644 --- a/test/indirect_iterator_test.cpp +++ b/test/indirect_iterator_test.cpp @@ -67,16 +67,6 @@ 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 { @@ -84,7 +74,7 @@ struct indirect_iterator_pair_generator typedef boost::indirect_iterator< typename Container::iterator - , indirect_const_iterator_traits + , typename iterator::value_type const > const_iterator; }; @@ -114,8 +104,10 @@ namespace boost { namespace detail }} #endif + void more_indirect_iterator_tests() { +# if 0 storage store(1000); std::generate(store.begin(), store.end(), rand); @@ -163,8 +155,8 @@ void more_indirect_iterator_tests() typedef boost::indirect_iterator indirect_set_iterator; typedef boost::indirect_iterator< iterator_set::iterator - , indirect_const_iterator_traits - > const_indirect_set_iterator; + , iterator_set::iterator::value_type const + > const_indirect_set_iterator; indirect_set_iterator sb(iter_set.begin()); indirect_set_iterator se(iter_set.end()); @@ -185,6 +177,7 @@ void more_indirect_iterator_tests() boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]); assert(std::equal(db, de, store.begin())); +#endif } int @@ -210,8 +203,8 @@ main() typedef boost::indirect_iterator< shared_t::iterator - , indirect_const_iterator_traits - > c_iter_t; + , boost::iterator_value::type const + > c_iter_t; # ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY boost::function_requires< boost_concepts::InteroperableConcept >(); @@ -229,7 +222,7 @@ main() typedef boost::indirect_iterator indirect_iterator; - typedef boost::indirect_iterator > + typedef boost::indirect_iterator const_indirect_iterator; indirect_iterator i(ptr); diff --git a/test/interoperable_fail.cpp b/test/interoperable_fail.cpp index ca5bae5..d3d869d 100644 --- a/test/interoperable_fail.cpp +++ b/test/interoperable_fail.cpp @@ -1,3 +1,8 @@ +// Copyright Thomas Witt 2003. 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. #include #include #include diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp index d72725b..c0819b3 100644 --- a/test/iterator_adaptor_test.cpp +++ b/test/iterator_adaptor_test.cpp @@ -1,6 +1,4 @@ -// Test boost/iterator_adaptors.hpp - -// (C) Copyright Jeremy Siek 2002. Permission to copy, use, modify, +// (C) Copyright Thomas Witt 2003. 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 @@ -8,44 +6,6 @@ // See http://www.boost.org for most recent version including documentation. -// Revision History -// 30 Nov 01 Added permutation_iterator.(Toon Knapen) -// 19 Nov 01 Added generator_iterator. (Jens Maurer) -// 04 Nov 01 Updated with respect to change in named parameters. -// (Jeremy Siek) -// 08 Mar 01 Moved indirect and transform tests to separate files. -// (Jeremy Siek) -// 19 Feb 01 Take adavantage of improved iterator_traits to do more tests -// on MSVC. Hack around an MSVC-with-STLport internal compiler -// error. (David Abrahams) -// 11 Feb 01 Added test of operator-> for forward and input iterators. -// (Jeremy Siek) -// 11 Feb 01 Borland fixes (David Abrahams) -// 10 Feb 01 Use new adaptors interface. (David Abrahams) -// 10 Feb 01 Use new filter_ interface. (David Abrahams) -// 09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace -// BOOST_NO_STD_ITERATOR_TRAITS with -// BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've -// normalized to core compiler capabilities (David Abrahams) -// 08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more -// comprehensive testing. Force-decay array function arguments to -// pointers. -// 07 Feb 01 Added tests for the make_xxx_iterator() helper functions. -// (Jeremy Siek) -// 07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where -// possible (which was all but the projection iterator). -// (Jeremy Siek) -// 06 Feb 01 Removed now-defaulted template arguments where possible -// Updated names to correspond to new generator naming convention. -// Added a trivial test for make_transform_iterator(). -// Gave traits for const iterators a mutable value_type, per std. -// Resurrected my original tests for indirect iterators. -// (David Abrahams) -// 04 Feb 01 Fix for compilers without standard iterator_traits -// (David Abrahams) -// 13 Jun 00 Added const version of the iterator tests (Jeremy Siek) -// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) - #include #include @@ -125,23 +85,24 @@ struct my_gen template struct ptr_iterator - : boost::iterator_adaptor - , V, V&, V* - , boost::iterator_tag - , std::ptrdiff_t> + : boost::iterator_adaptor< + ptr_iterator, + boost::iterator_traits_adaptor > + > { +private: + typedef iterator_adaptor super_t; +public: ptr_iterator() { } - ptr_iterator(V* d) : m_base(d) { } + ptr_iterator(V* d) : super_t(d) { } template ptr_iterator(const ptr_iterator& x) // should assert is_same add_cv add_cv - : m_base(x.base()) { } + : super_t(x.base()) { } - V*& base() { return m_base; } - V* const& base() const { return m_base; } -private: - V* m_base; }; int @@ -164,9 +125,7 @@ main() boost::const_nonconst_iterator_test(i, ++j); } - -#if 0 - // Test the named parameters + // Test the iterator_traits { // Test computation of defaults typedef boost::iterator_adaptor Pair; - Pair pair_array[N]; - for (int k = 0; k < N; ++k) - pair_array[k].first = array[k]; - - typedef boost::projection_iterator_pair_generator, - Pair*, const Pair* - > Projection; - - Projection::iterator i(pair_array); - boost::random_access_iterator_test(i, N, array); - - boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_()), N, array); - boost::random_access_iterator_test(boost::make_projection_iterator< select1st_ >(pair_array), N, array); - - Projection::const_iterator j(pair_array); - boost::random_access_iterator_test(j, N, array); - - boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_()), N, array); - boost::random_access_iterator_test(boost::make_const_projection_iterator >(pair_array), N, array); - - boost::const_nonconst_iterator_test(i, ++j); - } - - // Test reverse_iterator_generator - { - dummyT reversed[N]; - std::copy(array, array + N, reversed); - std::reverse(reversed, reversed + N); - - typedef boost::reverse_iterator_generator::type reverse_iterator; - - reverse_iterator i(reversed + N); - boost::random_access_iterator_test(i, N, array); - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) - boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); -#endif - - typedef boost::reverse_iterator_generator::type const_reverse_iterator; - - const_reverse_iterator j(reversed + N); - boost::random_access_iterator_test(j, N, array); - - const dummyT* const_reversed = reversed; - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) - boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); -#endif - - boost::const_nonconst_iterator_test(i, ++j); - } - - // Test reverse_iterator_generator again, with traits fully deducible on all platforms - { - std::deque reversed_container; - std::reverse_copy(array, array + N, std::back_inserter(reversed_container)); - const std::deque::iterator reversed = reversed_container.begin(); - - - typedef boost::reverse_iterator_generator< - std::deque::iterator>::type reverse_iterator; - typedef boost::reverse_iterator_generator< - std::deque::const_iterator, const dummyT>::type const_reverse_iterator; - - // MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation - // (e.g. "reversed + N") is used in the constructor below. - const std::deque::iterator finish = reversed_container.end(); - reverse_iterator i(finish); - - boost::random_access_iterator_test(i, N, array); - boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); - - const_reverse_iterator j = reverse_iterator(finish); - boost::random_access_iterator_test(j, N, array); - - const std::deque::const_iterator const_reversed = reversed; - boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); - - // Many compilers' builtin deque iterators don't interoperate well, though - // STLport fixes that problem. -#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && (!defined(BOOST_MSVC) || BOOST_MSVC > 1200) - boost::const_nonconst_iterator_test(i, ++j); -#endif - } - - // Test integer_range's iterators - { - int int_array[] = { 0, 1, 2, 3, 4, 5 }; - boost::integer_range r(0, 5); - boost::random_access_iterator_test(r.begin(), r.size(), int_array); - } - - // Test filter iterator - { - // Using typedefs for filter_gen::type confused Borland terribly. - typedef boost::detail::non_bidirectional_category::type category; - - typedef boost::filter_iterator_generator::type filter_iter; - -#if defined(__BORLANDC__) - // Borland is choking on accessing the policies_type explicitly - // from the filter_iter. - boost::forward_iterator_test(make_filter_iterator(array, array+N, - one_or_four()), - dummyT(1), dummyT(4)); -#else - filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N)); - boost::forward_iterator_test(i, dummyT(1), dummyT(4)); -#endif - -#if !defined(__BORLANDC__) - // - enum { is_forward = boost::is_same< - filter_iter::iterator_category, - std::forward_iterator_tag>::value }; - BOOST_STATIC_ASSERT(is_forward); -#endif - - // On compilers not supporting partial specialization, we can do more type - // deduction with deque iterators than with pointers... unless the library - // is broken ;-( -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || defined(__SGI_STL_PORT) - std::deque array2; - std::copy(array+0, array+N, std::back_inserter(array2)); - boost::forward_iterator_test( - boost::make_filter_iterator(array2.begin(), array2.end(), one_or_four()), - dummyT(1), dummyT(4)); - - boost::forward_iterator_test( - boost::make_filter_iterator(array2.begin(), array2.end()), - dummyT(1), dummyT(4)); -#endif - -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 // This just freaks MSVC out completely - boost::forward_iterator_test( - boost::make_filter_iterator( - boost::make_reverse_iterator(array2.end()), - boost::make_reverse_iterator(array2.begin()) - ), - dummyT(4), dummyT(1)); -#endif - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) - boost::forward_iterator_test( - boost::make_filter_iterator(array+0, array+N, one_or_four()), - dummyT(1), dummyT(4)); - - boost::forward_iterator_test( - boost::make_filter_iterator(array, array + N), - dummyT(1), dummyT(4)); - -#endif - } - // check operator-> with a forward iterator { boost::forward_iterator_archetype forward_iter; @@ -423,54 +213,6 @@ main() assert((*i).m_x == i->foo()); } - { - // check generator_iterator - my_gen g1; - boost::generator_iterator_generator::type gen = - boost::make_generator_iterator(g1); - assert(*gen == 1); - ++gen; - gen++; - assert(*gen == 3); - } - - { - // check permutation_iterator - typedef std::deque< int > element_range_type; - typedef std::list< int > index_type; - - static const int element_range_size = 10; - static const int index_size = 4; - - element_range_type elements( element_range_size ); - - for(element_range_type::iterator el_it = elements.begin(); - el_it != elements.end(); - ++el_it) - { - *el_it = std::distance( elements.begin(), el_it ); - } - - index_type indices( index_size ); - - for(index_type::iterator i_it = indices.begin(); - i_it != indices.end(); - ++i_it) - { - *i_it = element_range_size - index_size - + std::distance(indices.begin(), i_it ); - } - - std::reverse( indices.begin(), indices.end() ); - - typedef boost::permutation_iterator_generator< element_range_type::iterator, index_type::iterator >::type permutation_type; - permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() ); - permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() ); - - int expected_outcome[] = { 9, 8, 7, 6 }; - assert( std::equal( begin, end, expected_outcome ) ); - } -#endif std::cout << "test successful " << std::endl; return 0; } diff --git a/test/reverse_iterator_test.cpp b/test/reverse_iterator_test.cpp new file mode 100755 index 0000000..d94e746 --- /dev/null +++ b/test/reverse_iterator_test.cpp @@ -0,0 +1,87 @@ +// Copyright Thomas Witt 2003. 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. + +#include +#include + +// Test reverse iterator +int main() +{ +#if 0 + // Test reverse_iterator_generator + { + dummyT reversed[N]; + std::copy(array, array + N, reversed); + std::reverse(reversed, reversed + N); + + typedef boost::reverse_iterator_generator::type reverse_iterator; + + reverse_iterator i(reversed + N); + boost::random_access_iterator_test(i, N, array); + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) + boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); +#endif + + typedef boost::reverse_iterator_generator::type const_reverse_iterator; + + const_reverse_iterator j(reversed + N); + boost::random_access_iterator_test(j, N, array); + + const dummyT* const_reversed = reversed; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) + boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); +#endif + + boost::const_nonconst_iterator_test(i, ++j); + } + + // Test reverse_iterator_generator again, with traits fully deducible on all platforms + { + std::deque reversed_container; + std::reverse_copy(array, array + N, std::back_inserter(reversed_container)); + const std::deque::iterator reversed = reversed_container.begin(); + + + typedef boost::reverse_iterator_generator< + std::deque::iterator>::type reverse_iterator; + typedef boost::reverse_iterator_generator< + std::deque::const_iterator, const dummyT>::type const_reverse_iterator; + + // MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation + // (e.g. "reversed + N") is used in the constructor below. + const std::deque::iterator finish = reversed_container.end(); + reverse_iterator i(finish); + + boost::random_access_iterator_test(i, N, array); + boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); + + const_reverse_iterator j = reverse_iterator(finish); + boost::random_access_iterator_test(j, N, array); + + const std::deque::const_iterator const_reversed = reversed; + boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); + + // Many compilers' builtin deque iterators don't interoperate well, though + // STLport fixes that problem. +#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && (!defined(BOOST_MSVC) || BOOST_MSVC > 1200) + boost::const_nonconst_iterator_test(i, ++j); +#endif + } + +#endif + + +}