diff --git a/include/boost/iterator/counting_iterator.hpp b/include/boost/iterator/counting_iterator.hpp index d168e2d..d44be21 100644 --- a/include/boost/iterator/counting_iterator.hpp +++ b/include/boost/iterator/counting_iterator.hpp @@ -15,7 +15,12 @@ namespace boost { -template class counting_iterator; +template < + class Incrementable + , class CategoryOrTraversal + , class Difference +> +class counting_iterator; namespace detail { @@ -67,35 +72,38 @@ namespace detail }; BOOST_STATIC_ASSERT(is_numeric::value); - template + + template struct counting_iterator_base { - typedef typename mpl::apply_if< - is_same + typedef typename detail::ia_dflt_help< + CategoryOrTraversal , mpl::apply_if< is_numeric - , mpl::identity - , BOOST_ITERATOR_CATEGORY + , mpl::identity + , iterator_traversal > - , mpl::identity - >::type category; + >::type traversal; - typedef typename mpl::apply_if< - is_same + typedef typename detail::ia_dflt_help< + Difference , 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 + counting_iterator // self + , Incrementable // Base + , Incrementable // Value +# ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY + const // MSVC won't strip this. Instead we enable Thomas' + // criterion (see boost/iterator/detail/facade_iterator_category.hpp) +# endif + , traversal + , Incrementable const& // reference , difference > type; }; @@ -128,11 +136,20 @@ namespace detail }; } -template +template < + class Incrementable + , class CategoryOrTraversal = use_default + , class Difference = use_default +> class counting_iterator - : public detail::counting_iterator_base::type + : public detail::counting_iterator_base< + Incrementable, CategoryOrTraversal, Difference + >::type { - typedef typename detail::counting_iterator_base::type super_t; + typedef typename detail::counting_iterator_base< + Incrementable, CategoryOrTraversal, Difference + >::type super_t; + friend class iterator_core_access; public: diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp index 5a2e7eb..841ac4c 100644 --- a/include/boost/iterator/detail/categories.hpp +++ b/include/boost/iterator/detail/categories.hpp @@ -1,360 +1 @@ -// (C) Copyright Thomas Witt 2002. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#ifndef BOOST_ITERATOR_DETAIL_CATEGORIES_HPP -# define BOOST_ITERATOR_DETAIL_CATEGORIES_HPP - -# include -# include - -# include - -# include -# include - -# include -# include -# include -# include -# include -# include -# include - -# include - -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; - }; - - // - // Traversal Categories - // - struct incrementable_traversal_tag - { - typedef std::output_iterator_tag max_category; - }; - - struct single_pass_traversal_tag - : incrementable_traversal_tag - { - typedef detail::input_output_iterator_tag max_category; - }; - - struct forward_traversal_tag - : single_pass_traversal_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 { }; - - namespace detail - { - // - // Tag detection meta functions - // - - // I bet this is defined somewhere else. Let's wait and see. - struct error_type; - -# ifndef BOOST_NO_IS_CONVERTIBLE - - // True iff T is a tag "derived" from Tag - template - struct is_tag - : mpl::or_< - is_convertible - - // Because we can't actually get forward_iterator_tag to - // derive from input_output_iterator_tag, we need this - // case. - , mpl::and_< - is_convertible - , is_convertible - > - > - {}; - - -# 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_traversal, forward_traversal) - BOOST_ITERATOR_DERIVED_TAG1(incrementable_traversal, single_pass_traversal) - -# endif // BOOST_NO_IS_CONVERTIBLE workarounds - -# endif // ndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - template - struct known_tag - : mpl::apply_if, mpl::identity, Else> - {}; - - template - struct max_known_traversal_tag - : known_tag< - Tag, random_access_traversal_tag - , known_tag< - Tag, bidirectional_traversal_tag - , known_tag< - Tag, forward_traversal_tag - , known_tag< - Tag, single_pass_traversal_tag - , known_tag< - Tag, incrementable_traversal_tag - , error_iterator_tag - > - > - > - > - > - {}; - - // Doesn't cope with these odd combinations: readable+swappable, - // writable+swappable. That doesn't matter for the sake of - // new-style tag base computation, which is all it's used for - // anyway. - template - struct max_known_access_tag - : known_tag< - Tag, writable_lvalue_iterator_tag - , known_tag< - Tag, readable_lvalue_iterator_tag - , known_tag< - Tag, readable_writable_iterator_tag - , known_tag< - Tag, writable_iterator_tag - , known_tag< - Tag, readable_iterator_tag - , mpl::apply_if< - is_tag - , mpl::identity - , error_iterator_tag - > - > - > - > - > - > - {}; - - // - // Returns the minimum category type or error_type - // if T1 and T2 are unrelated. - // - // For compilers not supporting is_convertible this only - // works with the new boost return and traversal category - // types. The exact boost _types_ are required. No derived types - // will work. - // - // - template - struct minimum_category - : mpl::apply_if< - is_tag - , mpl::identity - , mpl::if_< - is_tag - , T2 - , error_type - > - > - { - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) - }; - -# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) - // Deal with ETI - template <> struct minimum_category { typedef minimum_category type; }; -# endif - - // - // Tag classification for use in iterator_adaptor - // - template - struct is_access_tag - : mpl::or_< - is_tag - , mpl::or_< - is_tag - , is_tag - > - > - {}; - - template - struct is_traversal_tag - : is_tag - {}; - - } // namespace detail - -} // namespace boost - -#include - -#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP +#error obsolete diff --git a/include/boost/iterator/detail/config_def.hpp b/include/boost/iterator/detail/config_def.hpp index 6789d4a..c31d71c 100644 --- a/include/boost/iterator/detail/config_def.hpp +++ b/include/boost/iterator/detail/config_def.hpp @@ -18,7 +18,66 @@ #include // for prior #include -#define BOOST_ITERATOR_CONFIG_DEF // if you get an error here, you have nested config_def #inclusion. +#ifdef BOOST_ITERATOR_CONFIG_DEF +# error you have nested config_def #inclusion. +#else +# define BOOST_ITERATOR_CONFIG_DEF +#endif + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) + +// Recall that in general, compilers without partial specialization +// can't strip constness. Consider counting_iterator, which normally +// passes a const Value to iterator_facade. As a result, any code +// which makes a std::vector of the iterator's value_type will fail +// when its allocator declares functions overloaded on reference and +// const_reference (the same type). +// +// Furthermore, Borland 5.5.1 drops constness in enough ways that we +// end up using a proxy for operator[] when we otherwise shouldn't. +// Using reference constness gives it an extra hint that it can +// return the value_type from operator[] directly, but is not +// strictly neccessary. Not sure how best to resolve this one. + +# define BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 1 + +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ + || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531)) \ + || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) +# define BOOST_NO_LVALUE_RETURN_DETECTION + +# if 0 // test code + struct v {}; + + typedef char (&no)[3]; + + template + no foo(T const&, ...); + + template + char foo(T&, int); + + + struct value_iterator + { + v operator*() const; + }; + + template + struct lvalue_deref_helper + { + static T& x; + enum { value = (sizeof(foo(*x,0)) == 1) }; + }; + + int z2[(lvalue_deref_helper::value == 1) ? 1 : -1]; + int z[(lvalue_deref_helper::value) == 1 ? -1 : 1 ]; +# endif + +#endif #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \ || BOOST_WORKAROUND(__GNUC__, <= 2 && __GNUC_MINOR__ <= 95) \ diff --git a/include/boost/iterator/detail/config_undef.hpp b/include/boost/iterator/detail/config_undef.hpp index f58df62..f93adae 100644 --- a/include/boost/iterator/detail/config_undef.hpp +++ b/include/boost/iterator/detail/config_undef.hpp @@ -18,6 +18,7 @@ #undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE #undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY #undef BOOST_ARG_DEPENDENT_TYPENAME +#undef BOOST_NO_LVALUE_RETURN_DETECTION #ifdef BOOST_ITERATOR_CONFIG_DEF # undef BOOST_ITERATOR_CONFIG_DEF diff --git a/include/boost/iterator/detail/facade_iterator_category.hpp b/include/boost/iterator/detail/facade_iterator_category.hpp new file mode 100755 index 0000000..9b2aa1a --- /dev/null +++ b/include/boost/iterator/detail/facade_iterator_category.hpp @@ -0,0 +1,214 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP +# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP + +# include + +# include + +# include // used in iterator_tag inheritance logic +# include +# include +# include +# include + +# include +# include +# include +# include + +# include + +# include // try to keep this last + +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY +# include +# endif + +// +// iterator_category deduction for iterator_facade +// + +// forward declaration +namespace boost { struct use_default; } + +namespace boost { namespace detail { + +struct input_output_iterator_tag + : std::input_iterator_tag +{ + // Using inheritance for only input_iterator_tag helps to avoid + // ambiguities when a stdlib implementation dispatches on a + // function which is overloaded on both input_iterator_tag and + // output_iterator_tag, as STLPort does, in its __valid_range + // function. I claim it's better to avoid the ambiguity in these + // cases. + operator std::output_iterator_tag() const + { + return std::output_iterator_tag(); + } +}; + +// +// True iff the user has explicitly disabled writability of this +// iterator. Pass the iterator_facade's Value parameter and its +// nested ::reference type. +// +template +struct iterator_writability_disabled +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic? + : mpl::or_< + is_const + , python::detail::is_reference_to_const + , is_const + > +# else + : is_const +# endif +{}; + + +// +// Convert an iterator_facade's traversal category, Value parameter, +// and ::reference type to an appropriate old-style category. +// +// If writability has been disabled per the above metafunction, the +// result will not be convertible to output_iterator_tag. +// +// Otherwise, if Traversal == single_pass_traversal_tag, the following +// conditions will result in a tag that is convertible both to +// input_iterator_tag and output_iterator_tag: +// +// 1. Reference is a reference to non-const +// 2. Reference is not a reference and is convertible to Value +// +template +struct iterator_facade_default_category + : mpl::apply_if< + mpl::and_< + is_reference + , is_convertible + > + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::if_< + is_convertible + , std::bidirectional_iterator_tag + , std::forward_iterator_tag + > + > + , typename mpl::apply_if< + mpl::and_< + is_convertible + + , mpl::or_< // check for readability + is_same + , is_convertible + > + > + , mpl::if_< + iterator_writability_disabled + , std::input_iterator_tag + , input_output_iterator_tag + > + + , mpl::identity + > + > +{ +}; + +// True iff T is convertible to an old-style iterator category. +template +struct is_iterator_category + : mpl::or_< + is_convertible + , is_convertible + > +{ +}; + +template +struct is_iterator_traversal + : is_convertible +{}; + +// +// A composite iterator_category tag convertible to Category (a pure +// old-style category) and Traversal (a pure traversal tag). +// Traversal must be a strict increase of the traversal power given by +// Category. +// +template +struct iterator_category_with_traversal + : Category, Traversal +{ +# if 0 + // Because of limitations on multiple user-defined conversions, + // this should be a good test of whether convertibility is enough + // in the spec, or whether we need to specify inheritance. + operator Category() const { return Category(); } + operator Traversal() const { return Traversal(); } +# endif + +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + // Make sure this isn't used to build any categories where + // convertibility to Traversal is redundant. Should just use the + // Category element in that case. + BOOST_STATIC_ASSERT( + !(is_convertible< + typename iterator_category_to_traversal::type + , Traversal + >::value)); + + BOOST_STATIC_ASSERT(is_iterator_category::value); + BOOST_STATIC_ASSERT(!is_iterator_category::value); + BOOST_STATIC_ASSERT(!is_iterator_traversal::value); + BOOST_STATIC_ASSERT(is_iterator_traversal::value); +# endif +}; + +// Computes an iterator_category tag whose traversal is Traversal and +// which is appropriate for an iterator +template +struct facade_iterator_category_impl +{ +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT(!is_iterator_category::value); +# endif + + typedef typename iterator_facade_default_category< + Traversal,ValueParam,Reference + >::type category; + + typedef typename mpl::if_< + is_same< + Traversal + , typename iterator_category_to_traversal::type + > + , category + , iterator_category_with_traversal + >::type type; +}; + +// +// Compute an iterator_category for iterator_facade +// +template +struct facade_iterator_category + : mpl::apply_if< + is_iterator_category + , mpl::identity // old-style categories are fine as-is + , facade_iterator_category_impl + > +{ +}; + +}} // namespace boost::detail + +# include + +#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP diff --git a/include/boost/iterator/detail/minimum_category.hpp b/include/boost/iterator/detail/minimum_category.hpp new file mode 100755 index 0000000..b1fcd9f --- /dev/null +++ b/include/boost/iterator/detail/minimum_category.hpp @@ -0,0 +1,98 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef MINIMUM_CATEGORY_DWA20031119_HPP +# define MINIMUM_CATEGORY_DWA20031119_HPP + +# include +# include + +# include + +namespace boost { namespace detail { +// +// Returns the minimum category type or error_type +// if T1 and T2 are unrelated. +// +// For compilers not supporting is_convertible this only +// works with the new boost return and traversal category +// types. The exact boost _types_ are required. No derived types +// will work. +// +// +template +struct minimum_category_impl; + +template +struct error_not_related_by_convertibility; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T2 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + BOOST_STATIC_ASSERT((is_same::value)); + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + : error_not_related_by_convertibility + { + }; +}; + +template +struct minimum_category +{ + typedef minimum_category_impl< + ::boost::is_convertible::value + , ::boost::is_convertible::value + > outer; + + typedef typename outer::template apply inner; + typedef typename inner::type type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) +}; + +template <> +struct minimum_category +{ + template + struct apply : minimum_category + {}; +}; + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) +template <> +struct minimum_category +{ + typedef int type; +}; +# endif + +}} // namespace boost::detail + +#endif // MINIMUM_CATEGORY_DWA20031119_HPP diff --git a/include/boost/iterator/filter_iterator.hpp b/include/boost/iterator/filter_iterator.hpp index cd490dc..fee0184 100644 --- a/include/boost/iterator/filter_iterator.hpp +++ b/include/boost/iterator/filter_iterator.hpp @@ -13,28 +13,42 @@ #include #include +#include +#include + namespace boost { + template + class filter_iterator; + namespace detail + { + template + struct filter_iterator_base + { + typedef iterator_adaptor< + filter_iterator + , Iterator + , use_default + , typename mpl::if_< + is_convertible< + typename iterator_traversal::type + , bidirectional_traversal_tag + > + , forward_traversal_tag + , use_default + >::type + > type; + }; + } + template class filter_iterator - : public iterator_adaptor< - filter_iterator, Iterator - , use_default - , typename detail::minimum_category< - bidirectional_traversal_tag - , typename traversal_category::type - >::type - > + : public detail::filter_iterator_base::type { - typedef iterator_adaptor< - filter_iterator, Iterator - , use_default - , typename detail::minimum_category< - bidirectional_traversal_tag - , typename traversal_category::type - >::type - > super_t; + typedef typename detail::filter_iterator_base< + Predicate, Iterator + >::type super_t; friend class iterator_core_access; diff --git a/include/boost/iterator/is_lvalue_iterator.hpp b/include/boost/iterator/is_lvalue_iterator.hpp index d77b977..4938151 100755 --- a/include/boost/iterator/is_lvalue_iterator.hpp +++ b/include/boost/iterator/is_lvalue_iterator.hpp @@ -4,16 +4,19 @@ #ifndef IS_LVALUE_ITERATOR_DWA2003112_HPP # define IS_LVALUE_ITERATOR_DWA2003112_HPP -#include -#include #include -#include +#include +#include + #include -// should be the last #include +// should be the last #includes +#include #include +#ifndef BOOST_NO_IS_CONVERTIBLE + namespace boost { namespace detail @@ -122,7 +125,7 @@ namespace detail {}; template - struct is_mutable_lvalue_iterator_impl + struct is_non_const_lvalue_iterator_impl : is_lvalue_iterator_impl< BOOST_DEDUCED_TYPENAME boost::detail::iterator_traits::value_type >::template rebind @@ -135,10 +138,13 @@ BOOST_TT_AUX_BOOL_TRAIT_DEF1( is_lvalue_iterator,T,::boost::detail::is_readable_lvalue_iterator_impl::value) BOOST_TT_AUX_BOOL_TRAIT_DEF1( - is_mutable_lvalue_iterator,T,::boost::detail::is_mutable_lvalue_iterator_impl::value) + is_non_const_lvalue_iterator,T,::boost::detail::is_non_const_lvalue_iterator_impl::value) } // namespace boost +#endif + #include +#include #endif // IS_LVALUE_ITERATOR_DWA2003112_HPP diff --git a/include/boost/iterator/is_readable_iterator.hpp b/include/boost/iterator/is_readable_iterator.hpp index 52df758..60d6ff0 100755 --- a/include/boost/iterator/is_readable_iterator.hpp +++ b/include/boost/iterator/is_readable_iterator.hpp @@ -13,6 +13,8 @@ // should be the last #include #include +#ifndef BOOST_NO_IS_CONVERTIBLE + namespace boost { namespace detail @@ -99,6 +101,8 @@ BOOST_TT_AUX_BOOL_TRAIT_DEF1( } // namespace boost +#endif + #include #endif // IS_READABLE_ITERATOR_DWA2003112_HPP diff --git a/include/boost/iterator/iterator_adaptor.hpp b/include/boost/iterator/iterator_adaptor.hpp index af14283..50694a1 100644 --- a/include/boost/iterator/iterator_adaptor.hpp +++ b/include/boost/iterator/iterator_adaptor.hpp @@ -26,12 +26,32 @@ #include #include +#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY +# include +#else +# include +#endif + #include #include namespace boost { + // Used as a default template argument internally, merely to + // indicate "use the default", this can also be passed by users + // explicitly in order to specify that the default should be used. + struct use_default; + +# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // the incompleteness of use_default causes massive problems for + // is_convertible (naturally). This workaround is fortunately not + // needed for vc6/vc7. + template + struct is_convertible + : mpl::false_ {}; +# endif + namespace detail { @@ -142,63 +162,51 @@ namespace boost class Derived , class Base , class Value - , class Category + , class Traversal , class Reference , class Difference > struct iterator_adaptor_base { - private: // intermediate results - - typedef typename mpl::apply_if< - mpl::or_< - is_same - , mpl::or_< - is_access_tag - , is_traversal_tag - > - > - , BOOST_ITERATOR_CATEGORY - , mpl::identity - >::type category; - - typedef typename detail::ia_dflt_help< - Reference - , mpl::apply_if< - is_same - , iterator_reference - , mpl::identity - > - >::type reference; - - public: // return type typedef iterator_facade< Derived - + +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY + , typename detail::ia_dflt_help< + Value + , mpl::apply_if< + is_same + , iterator_value + , remove_reference + > + >::type +# else , typename detail::ia_dflt_help< Value, iterator_value >::type - - , typename mpl::apply_if< - is_access_tag - , mpl::identity - , access_category_tag - >::type +# endif + + , typename detail::ia_dflt_help< + Traversal + , iterator_traversal + >::type + + , typename detail::ia_dflt_help< + Reference + , mpl::apply_if< + is_same + , iterator_reference + , add_reference + > + >::type - , typename mpl::apply_if< - is_traversal_tag - , mpl::identity - , traversal_category_tag - >::type - - , reference - , typename detail::ia_dflt_help< Difference, iterator_difference >::type > type; }; + template int static_assert_convertible_to(T); } // @@ -215,8 +223,8 @@ namespace boost // const. If const, a conforming compiler strips constness for the // value_type. If not supplied, iterator_traits::value_type is used // - // Category - the iterator_category of the resulting iterator. If not - // supplied, iterator_traits::iterator_category is used. + // Category - the traversal category of the resulting iterator. If not + // supplied, iterator_traversal::type is used. // // Reference - the reference type of the resulting iterator, and in // particular, the result type of operator*(). If not supplied but @@ -230,19 +238,19 @@ namespace boost class Derived , class Base , class Value = use_default - , class Category = use_default + , class Traversal = use_default , class Reference = use_default , class Difference = use_default > class iterator_adaptor : public detail::iterator_adaptor_base< - Derived, Base, Value, Category, Reference, Difference + Derived, Base, Value, Traversal, Reference, Difference >::type { friend class iterator_core_access; typedef typename detail::iterator_adaptor_base< - Derived, Base, Value, Category, Reference, Difference + Derived, Base, Value, Traversal, Reference, Difference >::type super_t; public: @@ -287,17 +295,18 @@ namespace boost // ); return m_iterator == x.base(); } - + + typedef typename iterator_category_to_traversal< + typename super_t::iterator_category + >::type my_traversal; + +# define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \ + typedef int assertion[sizeof(detail::static_assert_convertible_to(my_traversal()))]; +// BOOST_STATIC_ASSERT((is_convertible::value)); + void advance(typename super_t::difference_type n) { -# if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // seems to get instantiated incorrectly - BOOST_STATIC_ASSERT( - (detail::is_tag< - random_access_traversal_tag - , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal - >::value) - ); -# endif + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) m_iterator += n; } @@ -305,14 +314,7 @@ namespace boost void decrement() { -# if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) // seems to get instantiated incorrectly - BOOST_STATIC_ASSERT( - (detail::is_tag< - bidirectional_traversal_tag - , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal - >::value) - ); -# endif + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag) --m_iterator; } @@ -322,12 +324,7 @@ namespace boost typename super_t::difference_type distance_to( iterator_adaptor const& y) const { - BOOST_STATIC_ASSERT( - (detail::is_tag< - random_access_traversal_tag - , BOOST_ARG_DEPENDENT_TYPENAME super_t::iterator_category::traversal - >::value) - ); + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) // Maybe readd with same_distance // BOOST_STATIC_ASSERT( // (detail::same_category_and_difference::value) @@ -335,6 +332,8 @@ namespace boost return y.base() - m_iterator; } +# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL + private: // data members Base m_iterator; }; diff --git a/include/boost/iterator/iterator_archetypes.hpp b/include/boost/iterator/iterator_archetypes.hpp index e9439e7..b0ab188 100644 --- a/include/boost/iterator/iterator_archetypes.hpp +++ b/include/boost/iterator/iterator_archetypes.hpp @@ -8,341 +8,449 @@ #define BOOST_ITERATOR_ARCHETYPES_HPP #include -#include -#include #include #include +#include + +#include + #include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include #include -namespace boost +namespace boost { + +template +struct access_archetype; + +template +struct traversal_archetype; + +namespace iterator_archetypes { + enum { + readable_iterator_bit = 1 + , writable_iterator_bit = 2 + , swappable_iterator_bit = 4 + , lvalue_iterator_bit = 8 + }; - template - struct access_archetype; + // Not quite tags, since dispatching wouldn't work. + typedef mpl::int_::type readable_iterator_t; + typedef mpl::int_::type writable_iterator_t; + + typedef mpl::int_< + (readable_iterator_bit|writable_iterator_bit) + >::type readable_writable_iterator_t; + + typedef mpl::int_< + (readable_iterator_bit|lvalue_iterator_bit) + >::type readable_lvalue_iterator_t; + + typedef mpl::int_< + (lvalue_iterator_bit|writable_iterator_bit) + >::type writable_lvalue_iterator_t; + + typedef mpl::int_::type swappable_iterator_t; + typedef mpl::int_::type lvalue_iterator_t; - template - struct traversal_archetype; + template + struct has_access + : mpl::equal_to< + mpl::bitand_ + , Base + > + {}; +} - namespace detail { - - template - struct assign_proxy - { +namespace detail +{ + template + struct assign_proxy + { assign_proxy& operator=(T); - }; + }; - template - struct read_write_proxy : - assign_proxy - { + template + struct read_proxy + { operator T(); - }; + }; - template - struct arrow_proxy - { + template + struct read_write_proxy + : assign_proxy + , read_proxy + { + }; + + template + struct arrow_proxy + { T const* operator->() const; - }; + }; - struct no_operator_brackets {}; + struct no_operator_brackets {}; - template - struct readable_operator_brackets - { - ValueType operator[](std::ptrdiff_t n) const; - }; + template + struct readable_operator_brackets + { + read_proxy operator[](std::ptrdiff_t n) const; + }; - template - struct writable_operator_brackets - { + template + struct writable_operator_brackets + { read_write_proxy operator[](std::ptrdiff_t n) const; - }; + }; - template - struct operator_brackets : - mpl::if_< is_tag, - mpl::if_< is_tag, - writable_operator_brackets< Value >, - mpl::if_< is_tag, - readable_operator_brackets, - no_operator_brackets > >, - no_operator_brackets >::type - { - }; + template + struct operator_brackets + : mpl::aux::msvc_eti_base< + typename mpl::apply_if< + is_convertible + , mpl::apply_if< + iterator_archetypes::has_access< + AccessCategory + , iterator_archetypes::writable_iterator_t + > + , mpl::identity > + , mpl::if_< + iterator_archetypes::has_access< + AccessCategory + , iterator_archetypes::readable_iterator_t + > + , readable_operator_brackets + , no_operator_brackets + > + > + , mpl::identity + >::type + >::type + {}; + + template + struct traversal_archetype_impl + { + template struct archetype; + }; - template - struct traversal_archetype_impl - { - template struct archetype; - }; + template + struct traversal_archetype_ + : mpl::aux::msvc_eti_base< + typename traversal_archetype_impl::template archetype + >::type + {}; - template - struct traversal_archetype_ - : mpl::aux::msvc_eti_base< - typename traversal_archetype_impl::template archetype - >::type - {}; + template <> + struct traversal_archetype_impl + { + template + struct archetype + { + typedef void difference_type; - template <> - struct traversal_archetype_impl - { - template - struct archetype - { - typedef void difference_type; + Derived& operator++(); + Derived operator++(int) const; + }; + }; - Derived& operator++(); - Derived operator++(int) const; - }; - }; + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public equality_comparable< traversal_archetype_ >, + public traversal_archetype_ + { + }; + }; - template <> - struct traversal_archetype_impl - { - template - struct archetype - : public equality_comparable< traversal_archetype_ >, - public traversal_archetype_ - { - }; - }; - - template - bool operator==(traversal_archetype_ const&, - traversal_archetype_ const&); + template + bool operator==(traversal_archetype_ const&, + traversal_archetype_ const&); #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // doesn't seem to pick up != from equality_comparable - template - bool operator!=(traversal_archetype_ const&, - traversal_archetype_ const&); + template + bool operator!=(traversal_archetype_ const&, + traversal_archetype_ const&); #endif - template <> - struct traversal_archetype_impl - { - template - struct archetype - : public traversal_archetype_ - { - typedef std::ptrdiff_t difference_type; - }; - }; + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + typedef std::ptrdiff_t difference_type; + }; + }; - template <> - struct traversal_archetype_impl - { - template - struct archetype - : public traversal_archetype_ - { - Derived& operator--(); - Derived operator--(int) const; - }; - }; + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + Derived& operator--(); + Derived operator--(int) const; + }; + }; - template <> - struct traversal_archetype_impl - { - template - struct archetype - : public partially_ordered >, - public traversal_archetype_ - { - Derived& operator+=(std::ptrdiff_t); - Derived& operator-=(std::ptrdiff_t); - }; - }; + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public partially_ordered >, + public traversal_archetype_ + { + Derived& operator+=(std::ptrdiff_t); + Derived& operator-=(std::ptrdiff_t); + }; + }; - template - Derived& operator+(traversal_archetype_ const&, - std::ptrdiff_t); + template + Derived& operator+(traversal_archetype_ const&, + std::ptrdiff_t); - template - Derived& operator+(std::ptrdiff_t, - traversal_archetype_ const&); + template + Derived& operator+(std::ptrdiff_t, + traversal_archetype_ const&); - template - Derived& operator-(traversal_archetype_ const&, - std::ptrdiff_t); + template + Derived& operator-(traversal_archetype_ const&, + std::ptrdiff_t); - template - std::ptrdiff_t operator-(traversal_archetype_ const&, - traversal_archetype_ const&); + template + std::ptrdiff_t operator-(traversal_archetype_ const&, + traversal_archetype_ const&); - template - bool operator<(traversal_archetype_ const&, - traversal_archetype_ const&); + template + bool operator<(traversal_archetype_ const&, + traversal_archetype_ const&); - struct bogus_type; + struct bogus_type; + template + struct convertible_type + : mpl::if_< is_const, + typename remove_const::type, + bogus_type > + {}; + +} // namespace detail + + +template struct undefined; + +template +struct iterator_access_archetype_impl +{ + template struct archetype; +}; + +template +struct iterator_access_archetype + : mpl::aux::msvc_eti_base< + typename iterator_access_archetype_impl< + AccessCategory + >::template archetype + >::type +{ +}; + +template <> +struct iterator_access_archetype_impl< + iterator_archetypes::readable_iterator_t +> +{ template - struct convertible_type - : mpl::if_< is_const, - typename remove_const::type, - bogus_type > - {}; + struct archetype + { + typedef typename remove_cv::type value_type; + typedef Value reference; + typedef Value* pointer; - } // namespace detail + value_type operator*() const; + detail::arrow_proxy operator->() const; + }; +}; - template struct undefined; - - template - struct access_archetype_impl - { - template struct archetype; - }; - - template - struct access_archetype - : mpl::aux::msvc_eti_base< - typename access_archetype_impl::template archetype - >::type - { - }; - - template <> - struct access_archetype_impl - { - template - struct archetype - { - typedef typename remove_cv::type value_type; - typedef Value reference; - typedef Value* pointer; - - value_type operator*() const; - - detail::arrow_proxy operator->() const; - }; - }; - - template <> - struct access_archetype_impl - { - template - struct archetype - { +template <> +struct iterator_access_archetype_impl< + iterator_archetypes::writable_iterator_t +> +{ + template + struct archetype + { # if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - BOOST_STATIC_ASSERT(!is_const::value); + BOOST_STATIC_ASSERT(!is_const::value); # endif - typedef void value_type; - typedef void reference; - typedef void pointer; + typedef void value_type; + typedef void reference; + typedef void pointer; - detail::assign_proxy operator*() const; - }; - }; + detail::assign_proxy operator*() const; + }; +}; - template <> - struct access_archetype_impl - { - template - struct archetype - : public virtual access_archetype - { - typedef detail::read_write_proxy reference; - - detail::read_write_proxy operator*() const; - }; - }; - - template <> - struct access_archetype_impl - { - template - struct archetype - : public virtual access_archetype - { - typedef Value& reference; - - Value& operator*() const; - Value* operator->() const; - }; - }; - - template <> - struct access_archetype_impl - { - template - struct archetype - : public virtual access_archetype - { -# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - BOOST_STATIC_ASSERT((!is_const::value)); -# endif - }; - }; - - - template - struct iterator_archetype; - - template - struct traversal_archetype_base - : detail::operator_brackets< - typename remove_cv::type - , AccessCategory - , TraversalCategory - > - , detail::traversal_archetype_< - iterator_archetype - , Value - , TraversalCategory +template <> +struct iterator_access_archetype_impl< + iterator_archetypes::readable_writable_iterator_t +> +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, iterator_archetypes::readable_iterator_t > - { - }; + { + typedef detail::read_write_proxy reference; - template - struct iterator_archetype - : public traversal_archetype_base - , public access_archetype + detail::read_write_proxy operator*() const; + }; +}; - // These broken libraries require derivation from std::iterator - // (or related magic) in order to handle iter_swap and other - // iterator operations -# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ - || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) - , public std::iterator< - iterator_tag - , typename access_archetype::value_type - , typename traversal_archetype_base< - Value, AccessCategory, TraversalCategory - >::difference_type - > +template <> +struct iterator_access_archetype_impl +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, iterator_archetypes::readable_iterator_t + > + { + typedef Value& reference; + + Value& operator*() const; + Value* operator->() const; + }; +}; + +template <> +struct iterator_access_archetype_impl +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, iterator_archetypes::readable_lvalue_iterator_t + > + { +# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + BOOST_STATIC_ASSERT((!is_const::value)); # endif + }; +}; + + +template +struct iterator_archetype; + +template +struct traversal_archetype_base + : detail::operator_brackets< + typename remove_cv::type + , AccessCategory + , TraversalCategory + > + , detail::traversal_archetype_< + iterator_archetype + , Value + , TraversalCategory + > +{ +}; + +namespace detail +{ + template + struct iterator_archetype_base + : iterator_access_archetype + , traversal_archetype_base { - // Derivation from std::iterator above caused ambiguity, so now - // we have to declare all the types here. + typedef iterator_access_archetype access; + + typedef typename detail::facade_iterator_category< + TraversalCategory + , typename mpl::apply_if< + iterator_archetypes::has_access< + AccessCategory, iterator_archetypes::writable_iterator_t + > + , remove_const + , add_const + >::type + , typename access::reference + >::type iterator_category; + + // Needed for some broken libraries (see below) + typedef boost::iterator< + iterator_category + , Value + , typename traversal_archetype_base< + Value, AccessCategory, TraversalCategory + >::difference_type + , typename access::pointer + , typename access::reference + > workaround_iterator_base; + }; +} + +template +struct iterator_archetype + : public detail::iterator_archetype_base + + // These broken libraries require derivation from std::iterator + // (or related magic) in order to handle iter_swap and other + // iterator operations # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) - typedef typename access_archetype::value_type value_type; - - typedef typename access_archetype::pointer pointer; - - typedef typename access_archetype::reference reference; - - typedef typename traversal_archetype_base< - Value, AccessCategory, TraversalCategory - >::difference_type difference_type; + , public detail::iterator_archetype_base< + Value, AccessCategory, TraversalCategory + >::workaround_iterator_base +# endif +{ + // Derivation from std::iterator above caused references to nested + // types to be ambiguous, so now we have to redeclare them all + // here. +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) + + typedef detail::iterator_archetype_base< + Value,AccessCategory,TraversalCategory + > base; + + typedef typename base::value_type value_type; + typedef typename base::reference reference; + typedef typename base::pointer pointer; + typedef typename base::difference_type difference_type; + typedef typename base::iterator_category iterator_category; # endif - - typedef iterator_tag iterator_category; - iterator_archetype(); - iterator_archetype(iterator_archetype const&); + iterator_archetype(); + iterator_archetype(iterator_archetype const&); - iterator_archetype& operator=(iterator_archetype const&); + iterator_archetype& operator=(iterator_archetype const&); - // Optional conversion from mutable - // iterator_archetype(iterator_archetype::type, AccessCategory, TraversalCategory> const&); - }; + // Optional conversion from mutable + // iterator_archetype(iterator_archetype::type, AccessCategory, TraversalCategory> const&); +}; } // namespace boost diff --git a/include/boost/iterator/iterator_categories.hpp b/include/boost/iterator/iterator_categories.hpp index cbf1f2f..7b4f9ae 100644 --- a/include/boost/iterator/iterator_categories.hpp +++ b/include/boost/iterator/iterator_categories.hpp @@ -4,425 +4,159 @@ // "as is" without express or implied warranty, and with no claim as // to its suitability for any purpose. -// TODO: -// Add separate category tag for operator[]. - #ifndef BOOST_ITERATOR_CATEGORIES_HPP -#define BOOST_ITERATOR_CATEGORIES_HPP +# define BOOST_ITERATOR_CATEGORIES_HPP -#include -#include +# include +# include +# include -#include -#include +# include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT +# include +# include # include -#endif +# include -#include +# include -#include // must be last #include - -#if BOOST_WORKAROUND(__MWERKS__, <=0x2407) -# define BOOST_NO_IS_CONVERTIBLE // "Convertible does not provide enough/is not working" -#endif +# include namespace boost { - namespace detail - { - // Helper metafunction for std_category below - template - struct match_tag - : mpl::apply_if, mpl::identity, Next> - { - }; - - // 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_traversal_tag type; - - template - struct apply - : mpl::identity {}; - - }; - - template <> - struct std_to_new_tags - { - typedef incrementable_traversal_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 - // something less sophisticated. - // - // The solution depends on the fact that only - // std iterator categories work with is_xxx_iterator - // meta functions, as BOOST_NO_IS_CONVERTIBLE is - // defined for cwpro7. - // - template - struct is_new_iterator_tag - : mpl::not_< - mpl::or_< - is_tag - , is_tag - > - > - {}; - -#elif BOOST_WORKAROUND(__GNUC__, == 2 && __GNUC_MINOR__ == 95) \ - || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) - - template - struct is_new_iterator_tag - : is_boost_iterator_tag - { - }; - -#else - - BOOST_MPL_HAS_XXX_TRAIT_DEF(traversal) - - template - struct is_new_iterator_tag - : mpl::if_< - is_class - , has_traversal - , mpl::false_ - >::type - { - }; - -#endif - - } // namespace detail +// +// Traversal Categories +// +struct incrementable_traversal_tag {}; - namespace detail { - - template - struct get_traversal_category { - typedef typename NewCategoryTag::traversal type; - }; - - // Remove all writability from the given access tag. This - // functionality is part of new_category_to_access in order to - // support deduction of the proper default access category for - // iterator_adaptor; when the reference type is a reference to - // constant we must strip writability. - template - struct remove_access_writability - : mpl::apply_if< - is_tag - , mpl::identity - - , mpl::apply_if< - is_tag - , mpl::identity - - , mpl::if_< - is_tag - // Is this OK? I think it may correct be for all - // legitimate cases, because at this point the - // iterator is not readable, so it could not have - // been any more than writable + swappable. - , swappable_iterator_tag - , AccessTag - > - > - > - {}; +struct single_pass_traversal_tag + : incrementable_traversal_tag {}; - template - struct new_category_to_access - : mpl::apply_if< - python::detail::is_reference_to_const - , remove_access_writability - , mpl::identity - > - {}; +struct forward_traversal_tag + : single_pass_traversal_tag {}; + +struct bidirectional_traversal_tag + : forward_traversal_tag {}; + +struct random_access_traversal_tag + : bidirectional_traversal_tag {}; - template - struct access_category_tag - : mpl::apply_if< - is_new_iterator_tag - , new_category_to_access - , iter_category_to_access +namespace detail +{ + // + // Convert a "strictly old-style" iterator category to a traversal + // tag. This is broken out into a separate metafunction to reduce + // the cost of instantiating iterator_category_to_traversal, below, + // for new-style types. + // + template + struct old_category_to_traversal + : mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , void + > + > + > > - { - }; - - template - struct traversal_category_tag - : 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 { typedef void type; }; - template <> struct traversal_category_tag { typedef void type; }; -# endif - - // iterator_tag_base - a metafunction to compute the appropriate - // old-style tag (if any) to use as a base for a new-style tag. - template - struct iterator_tag_base - : minimum_category< - typename KnownAccessTag::max_category - , typename KnownTraversalTag::max_category - > - {}; - -# if BOOST_WORKAROUND(BOOST_MSVC,<=1200) - template <> - struct iterator_tag_base - : mpl::false_ {}; // just using false_ so that the result will be - // a legal base class -# endif - - // specialization for this special case. Otherwise we get - // input_output_iterator_tag, because the standard hierarchy has a - // sudden anomalous distinction between readability and - // writability at the level of input iterator/output iterator. - template <> - struct iterator_tag_base< - readable_lvalue_iterator_tag,single_pass_traversal_tag> - { - typedef std::input_iterator_tag type; - }; - - } // namespace detail - - template - struct access_category - : detail::access_category_tag< - typename detail::iterator_traits::iterator_category - , typename detail::iterator_traits::reference> + > {}; - template - struct traversal_category - : detail::traversal_category_tag< - typename detail::iterator_traits::iterator_category +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + template <> + struct old_category_to_traversal + { + typedef int type; + }; +# endif + + template + struct pure_traversal_tag + : mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , mpl::apply_if< + is_convertible + , mpl::identity + , void + > + > + > + > > { }; + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + template <> + struct pure_traversal_tag + { + typedef int type; + }; +# endif + +} // namespace detail + + +// +// Convert an iterator category into a traversal tag +// +template +struct iterator_category_to_traversal + : mpl::apply_if< // if already convertible to a traversal tag, we're done. + is_convertible + , mpl::identity + , detail::old_category_to_traversal + > +{}; + +// Trait to get an iterator's traversal category +template +struct iterator_traversal + : iterator_category_to_traversal< + typename boost::detail::iterator_traits::iterator_category + > +{}; # ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT - // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work - // out well. Instantiating the nested apply template also - // requires instantiating iterator_traits on the - // placeholder. Instead we just specialize it as a metafunction - // class. +// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work +// out well. Instantiating the nested apply template also +// requires instantiating iterator_traits on the +// placeholder. Instead we just specialize it as a metafunction +// class. template <> - struct access_category - { - template - struct apply : access_category - {}; - }; - - template <> - struct traversal_category - { - template - struct apply : traversal_category - {}; - }; -# endif - -# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - - template - struct access_category - : mpl::if_< - is_const - , readable_lvalue_iterator_tag - , writable_lvalue_iterator_tag> - { - }; - - template - struct traversal_category - { - typedef random_access_traversal_tag type; - }; - -# endif - - template - struct iterator_tag - : detail::iterator_tag_base< - typename detail::max_known_access_tag::type - , typename detail::max_known_traversal_tag::type - >::type - { - typedef AccessTag access; - typedef TraversalTag traversal; - }; - - namespace detail - { -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +struct iterator_traversal +{ template - struct is_boost_iterator_tag - : mpl::false_ {}; - - template - struct is_boost_iterator_tag > - : mpl::true_ {}; -# else - template - struct is_boost_iterator_tag - { - typedef char (&yes)[1]; - typedef char (&no)[2]; - - template - static yes test(mpl::identity >*); - static no test(...); - - static mpl::identity* inst; - BOOST_STATIC_CONSTANT(bool, value = sizeof(test(inst)) == sizeof(yes)); - typedef mpl::bool_ type; - }; + struct apply : iterator_traversal + {}; +}; +template <> +struct iterator_traversal + : iterator_traversal +{}; # endif - } } // namespace boost diff --git a/include/boost/iterator/iterator_concepts.hpp b/include/boost/iterator/iterator_concepts.hpp index 31dd265..c549999 100644 --- a/include/boost/iterator/iterator_concepts.hpp +++ b/include/boost/iterator/iterator_concepts.hpp @@ -15,16 +15,20 @@ #include #include -#include -#include -#include -#include -#include -#include // Use boost::detail::iterator_traits to work around some MSVC/Dinkumware problems. #include +#include +#include + +#include +#include +#include +#include + +#include + // Use boost/limits to work around missing limits headers on some compilers #include @@ -56,7 +60,6 @@ namespace boost_concepts { public: 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 >(); @@ -64,8 +67,6 @@ namespace boost_concepts { boost::function_requires< boost::DefaultConstructibleConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); - reference r = *i; // or perhaps read(x) value_type v(r); boost::ignore_unused_variable_warning(v); @@ -73,19 +74,19 @@ namespace boost_concepts { Iterator i; }; - template + template < + typename Iterator + , typename ValueType = typename boost::detail::iterator_traits::value_type + > class WritableIteratorConcept { public: - typedef typename boost::access_category::type access_category; - + void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); boost::function_requires< boost::EqualityComparableConcept >(); boost::function_requires< boost::DefaultConstructibleConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); - *i = v; // a good alternative could be something like write(x, v) } ValueType v; @@ -95,11 +96,8 @@ namespace boost_concepts { template class SwappableIteratorConcept { public: - typedef typename boost::access_category::type access_category; void constraints() { - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); - std::iter_swap(i1, i2); } Iterator i1; @@ -107,25 +105,25 @@ namespace boost_concepts { }; template - class ReadableLvalueIteratorConcept { - public: - typedef typename boost::detail::iterator_traits::value_type value_type; - typedef typename boost::detail::iterator_traits::reference reference; - typedef typename boost::access_category::type access_category; + class ReadableLvalueIteratorConcept + { + public: + typedef typename boost::detail::iterator_traits::value_type value_type; + typedef typename boost::detail::iterator_traits::reference reference; - void constraints() { - boost::function_requires< ReadableIteratorConcept >(); + void constraints() + { + boost::function_requires< ReadableIteratorConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); - - typedef boost::mpl::or_< - boost::is_same, - boost::is_same > correct_reference; + typedef boost::mpl::or_< + boost::is_same + , boost::is_same + > correct_reference; - BOOST_STATIC_ASSERT(correct_reference::value); + BOOST_STATIC_ASSERT(correct_reference::value); - reference v = *i; - boost::ignore_unused_variable_warning(v); + reference v = *i; + boost::ignore_unused_variable_warning(v); } Iterator i; }; @@ -135,7 +133,6 @@ 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::access_category::type access_category; void constraints() { boost::function_requires< @@ -145,7 +142,6 @@ namespace boost_concepts { boost::function_requires< SwappableIteratorConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); BOOST_STATIC_ASSERT((boost::is_same::value)); } @@ -157,14 +153,19 @@ namespace boost_concepts { template class IncrementableIteratorConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; void constraints() { boost::function_requires< boost::SGIAssignableConcept >(); boost::function_requires< boost::DefaultConstructibleConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + BOOST_STATIC_ASSERT( + (boost::is_convertible< + traversal_category + , boost::incrementable_traversal_tag + >::value + )); ++i; (void)i++; @@ -175,21 +176,26 @@ namespace boost_concepts { template class SinglePassIteratorConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; void constraints() { boost::function_requires< IncrementableIteratorConcept >(); boost::function_requires< boost::EqualityComparableConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + BOOST_STATIC_ASSERT( + (boost::is_convertible< + traversal_category + , boost::single_pass_traversal_tag + >::value + )); } }; template class ForwardTraversalConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; void constraints() { @@ -201,19 +207,29 @@ namespace boost_concepts { > difference_type_is_signed_integral; BOOST_STATIC_ASSERT(difference_type_is_signed_integral::value); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + BOOST_STATIC_ASSERT( + (boost::is_convertible< + traversal_category + , boost::forward_traversal_tag + >::value + )); } }; template class BidirectionalTraversalConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; void constraints() { boost::function_requires< ForwardTraversalConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + BOOST_STATIC_ASSERT( + (boost::is_convertible< + traversal_category + , boost::bidirectional_traversal_tag + >::value + )); --i; (void)i--; @@ -224,14 +240,19 @@ namespace boost_concepts { template class RandomAccessTraversalConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; void constraints() { boost::function_requires< BidirectionalTraversalConcept >(); - BOOST_STATIC_ASSERT((boost::detail::is_tag::value)); + BOOST_STATIC_ASSERT( + (boost::is_convertible< + traversal_category + , boost::random_access_traversal_tag + >::value + )); i += n; i = i + n; @@ -326,11 +347,11 @@ namespace detail class InteroperableConcept { public: - typedef typename boost::traversal_category::type traversal_category; + typedef typename boost::iterator_traversal::type traversal_category; typedef typename boost::detail::iterator_traits::difference_type difference_type; - typedef typename boost::traversal_category::type + typedef typename boost::iterator_traversal::type const_traversal_category; typedef typename boost::detail::iterator_traits::difference_type const_difference_type; diff --git a/include/boost/iterator/iterator_facade.hpp b/include/boost/iterator/iterator_facade.hpp index 2ed5a16..79b2d3c 100644 --- a/include/boost/iterator/iterator_facade.hpp +++ b/include/boost/iterator/iterator_facade.hpp @@ -12,15 +12,17 @@ #include #include -#include #include + +#include #include #include +#include +#include +#include #include -#include - #include #include @@ -30,21 +32,7 @@ namespace boost { // This forward declaration is required for the friend declaration // in iterator_core_access - template class iterator_facade; - - // Used as a default template argument internally, merely to - // indicate "use the default", this can also be passed by users - // explicitly in order to specify that the default should be used. - struct use_default; - -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - // the incompleteness of use_default causes massive problems for - // is_convertible (naturally). This workaround is fortunately not - // needed for vc6/vc7. - template - struct is_convertible - : mpl::false_ {}; -# endif + template class iterator_facade; namespace detail { @@ -75,59 +63,30 @@ namespace boost #endif }; - // - // Add const qualification for iterators which are not writable - // - template - struct const_qualified_ref : - mpl::if_< is_tag< writable_iterator_tag, AccessCategory >, - Value&, - Value const& > - {}; - - // The apparent duplication here works around a Borland problem - template - struct const_qualified_ptr : - mpl::if_< is_tag< writable_iterator_tag, AccessCategory >, - Value*, - Value const* > - {}; - - // - // Generates the associated types for an iterator_facade with the - // given parameters. Additionally generates a 'base' type for - // compiler/library combinations which require user-defined - // iterators to inherit from std::iterator. + // Generates associated types for an iterator_facade with the + // given parameters. // template < - class Value - , class AccessCategory - , class TraversalCategory - , class Reference + class ValueParam + , class CategoryOrTraversal + , class Reference , class Difference > struct iterator_facade_types { - typedef iterator_tag iterator_category; - - typedef typename remove_cv::type value_type; - - typedef Difference difference_type; - - typedef typename const_qualified_ptr::type pointer; - - // The use_default support is needed for iterator_adaptor. - // For practical reasons iterator_adaptor needs to specify - // a fixed number of template arguments of iterator_facade. - // So use_default is its way to say: "What I really mean - // is your default parameter". - typedef typename mpl::if_< - is_same - , typename const_qualified_ref::type - , Reference - >::type reference; - + typedef typename facade_iterator_category< + CategoryOrTraversal, ValueParam, Reference + >::type iterator_category; + + typedef typename remove_const::type value_type; + + typedef typename mpl::apply_if< + detail::iterator_writability_disabled + , add_pointer::type> + , add_pointer + >::type pointer; + # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \ || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \ @@ -141,7 +100,7 @@ namespace boost # define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1 typedef - iterator + iterator base; # endif }; @@ -205,10 +164,10 @@ namespace boost public: operator_brackets_proxy(Iterator const& iter) - : m_iter(iter) + : m_iter(iter) {} - operator reference() + operator reference() const { return *m_iter; } @@ -223,28 +182,24 @@ namespace boost Iterator m_iter; }; - template + template struct operator_brackets_result { - typedef typename access_category_tag::type access_category; - - typedef is_tag use_proxy; - typedef typename mpl::if_< - use_proxy + iterator_writability_disabled + , Value , operator_brackets_proxy - , ValueType >::type type; }; template - operator_brackets_proxy make_operator_brackets_result(Iterator const& iter, mpl::true_) + operator_brackets_proxy make_operator_brackets_result(Iterator const& iter, mpl::false_) { return operator_brackets_proxy(iter); } template - typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_) + typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::true_) { return *iter; } @@ -253,20 +208,20 @@ namespace boost // Macros which describe the declarations of binary operators -# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ - template < \ - class Derived1, class V1, class AC1, class TC1, class R1, class D1 \ - , class Derived2, class V2, class AC2, class TC2, class R2, class D2 \ - > \ - prefix typename detail::enable_if_interoperable< \ - Derived1, Derived2, result_type \ - >::type \ - operator op( \ - iterator_facade const& lhs \ - , iterator_facade const& rhs) +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ + template < \ + class Derived1, class V1, class TC1, class R1, class D1 \ + , class Derived2, class V2, class TC2, class R2, class D2 \ + > \ + prefix typename detail::enable_if_interoperable< \ + Derived1, Derived2, result_type \ + >::type \ + operator op( \ + iterator_facade const& lhs \ + , iterator_facade const& rhs) -# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ - template \ +# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ + template \ prefix Derived operator+ args // @@ -286,8 +241,8 @@ namespace boost // to work in the absence of member template friends. public: # else - - template friend class iterator_facade; + + template friend class iterator_facade; # define BOOST_ITERATOR_FACADE_RELATION(op) \ BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, bool); @@ -306,8 +261,8 @@ namespace boost ; BOOST_ITERATOR_FACADE_PLUS_HEAD( - friend - , (iterator_facade const& + friend + , (iterator_facade const& , typename Derived::difference_type) ) ; @@ -315,7 +270,7 @@ namespace boost BOOST_ITERATOR_FACADE_PLUS_HEAD( friend , (typename Derived::difference_type - , iterator_facade const&) + , iterator_facade const&) ) ; @@ -370,26 +325,21 @@ namespace boost template < class Derived // The derived iterator type being constructed , class Value - , class AccessCategory - , class TraversalCategory - , class Reference = BOOST_DEDUCED_TYPENAME detail::const_qualified_ref::type + , class CategoryOrTraversal + , class Reference = Value& , class Difference = std::ptrdiff_t > class iterator_facade # ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE : public detail::iterator_facade_types< - Value, AccessCategory, TraversalCategory, Reference, Difference + Value, CategoryOrTraversal, Reference, Difference >::base # undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE # endif { private: - typedef typename - detail::iterator_facade_types - types; - // - // Curiously Recursive Template interface. + // Curiously Recurring Template interface. // typedef Derived derived_t; @@ -403,13 +353,17 @@ namespace boost return static_cast(*this); } + typedef detail::iterator_facade_types< + Value, CategoryOrTraversal, Reference, Difference + > associated_types; + public: - typedef typename types::value_type value_type; - typedef typename types::reference reference; - typedef typename types::difference_type difference_type; - typedef typename types::pointer pointer; - typedef typename types::iterator_category iterator_category; + typedef typename associated_types::value_type value_type; + typedef Reference reference; + typedef Difference difference_type; + typedef typename associated_types::pointer pointer; + typedef typename associated_types::iterator_category iterator_category; reference operator*() const { @@ -429,15 +383,17 @@ namespace boost , pointer >::make(*this->derived()); } - - typename detail::operator_brackets_result::type + + typename detail::operator_brackets_result::type operator[](difference_type n) const { - typedef typename - detail::operator_brackets_result::use_proxy - use_proxy; - - return detail::make_operator_brackets_result(this->derived() + n, use_proxy()); + typedef detail::iterator_writability_disabled + not_writable; + + return detail::make_operator_brackets_result( + this->derived() + n + , not_writable() + ); } Derived& operator++() @@ -615,13 +571,13 @@ namespace boost } BOOST_ITERATOR_FACADE_PLUS(( - iterator_facade const& i + iterator_facade const& i , typename Derived::difference_type n )) BOOST_ITERATOR_FACADE_PLUS(( typename Derived::difference_type n - , iterator_facade const& i + , iterator_facade const& i )) # undef BOOST_ITERATOR_FACADE_PLUS # undef BOOST_ITERATOR_FACADE_PLUS_HEAD diff --git a/include/boost/iterator/new_iterator_tests.hpp b/include/boost/iterator/new_iterator_tests.hpp index 759f8de..c16b826 100644 --- a/include/boost/iterator/new_iterator_tests.hpp +++ b/include/boost/iterator/new_iterator_tests.hpp @@ -24,15 +24,13 @@ # include // for detail::dummy_constructor # include # include +# include +# include + +# include namespace boost { -void is_readable(readable_iterator_tag) { } -void is_writable(writable_iterator_tag) { } -void is_swappable(swappable_iterator_tag) { } -void is_constant_lvalue(readable_lvalue_iterator_tag) { } -void is_mutable_lvalue(writable_lvalue_iterator_tag) { } - // Preconditions: *i == v template void readable_iterator_test(const Iterator i1, T v) @@ -45,8 +43,12 @@ void readable_iterator_test(const Iterator i1, T v) T v2 = r2; assert(v1 == v); assert(v2 == v); - typedef typename access_category::type result_category; - is_readable(result_category()); + +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + // I think we don't really need this as it checks the same things as + // the above code. + BOOST_STATIC_ASSERT(is_readable_iterator::value); +# endif } template @@ -54,7 +56,6 @@ void writable_iterator_test(Iterator i, T v) { Iterator i2(i); // Copy Constructible *i2 = v; - is_writable(typename access_category::type()); } template @@ -65,8 +66,6 @@ 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 access_category::type result_category; - is_swappable(result_category()); } template @@ -78,12 +77,14 @@ void constant_lvalue_iterator_test(Iterator i, T v1) BOOST_STATIC_ASSERT((is_same::value)); const T& v2 = *i2; assert(v1 == v2); - typedef typename access_category::type result_category; - is_constant_lvalue(result_category()); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!is_non_const_lvalue_iterator::value); +# endif } template -void mutable_lvalue_iterator_test(Iterator i, T v1, T v2) +void non_const_lvalue_iterator_test(Iterator i, T v1, T v2) { Iterator i2(i); typedef typename detail::iterator_traits::value_type value_type; @@ -91,11 +92,17 @@ void mutable_lvalue_iterator_test(Iterator i, T v1, T v2) BOOST_STATIC_ASSERT((is_same::value)); T& v3 = *i2; assert(v1 == v3); + + // A non-const lvalue iterator is not neccessarily writable, but we + // are assuming the value_type is assignable here *i = v2; + T& v4 = *i2; assert(v2 == v4); - typedef typename access_category::type result_category; - is_mutable_lvalue(result_category()); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(is_non_const_lvalue_iterator::value); +# endif } template @@ -159,7 +166,6 @@ void bidirectional_readable_iterator_test(Iterator i, T v1, T v2) readable_iterator_test(i2, v2); } - // random access // Preconditions: [i,i+N) is a valid range template @@ -169,10 +175,12 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) const Iterator j = i; int c; - for (c = 0; c < N-1; ++c) { + for (c = 0; c < N-1; ++c) + { assert(i == j + c); assert(*i == vals[c]); - assert(*i == j[c]); + typename detail::iterator_traits::value_type x = j[c]; + assert(*i == x); assert(*i == *(j + c)); assert(*i == *(c + j)); ++i; @@ -183,10 +191,12 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) } Iterator k = j + N - 1; - for (c = 0; c < N-1; ++c) { + for (c = 0; c < N-1; ++c) + { assert(i == k - c); assert(*i == vals[N - 1 - c]); - assert(*i == j[N - 1 - c]); + typename detail::iterator_traits::value_type x = j[N - 1 - c]; + assert(*i == x); Iterator q = k - c; assert(*i == *q); assert(i > j); @@ -197,8 +207,8 @@ void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) } } -// #if 0'd code snipped; see CVS v 1.4 if you need it back - } // namespace boost +# include + #endif // BOOST_NEW_ITERATOR_TESTS_HPP diff --git a/include/boost/iterator/transform_iterator.hpp b/include/boost/iterator/transform_iterator.hpp index cb41f07..3474ccf 100644 --- a/include/boost/iterator/transform_iterator.hpp +++ b/include/boost/iterator/transform_iterator.hpp @@ -24,6 +24,8 @@ #include #include +#include + namespace boost { template @@ -46,53 +48,38 @@ namespace boost }; #endif - // Given the transform iterator's transformation and iterator, this - // is the type used as its traits. + // Compute the iterator_adaptor instantiation to be used for transform_iterator template struct transform_iterator_base { - private: + private: + // By default, dereferencing the iterator yields the same as + // the function. Do we need to adjust the way + // function_object_result is computed for the standard + // proposal (e.g. using Doug's result_of)? + typedef typename ia_dflt_help< + Reference + , function_object_result + >::type reference; - // transform_iterator does not support writable/swappable iterators -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - BOOST_STATIC_ASSERT((is_tag< readable_iterator_tag, typename access_category::type >::value)); -#endif - - typedef typename mpl::apply_if< - is_same< Reference, use_default > - , function_object_result - , mpl::identity - >::type result_type; + // To get the default for Value: remove any reference on the + // result type, but retain any constness to signal + // non-writability. Note that if we adopt Thomas' suggestion + // to key non-writability *only* on the Reference argument, + // we'd need to strip constness here as well. + typedef typename ia_dflt_help< + Value + , remove_reference + >::type cv_value_type; - typedef typename mpl::if_< - is_same< Value, use_default > - , typename remove_reference< result_type >::type - , Value - >::type cv_value_type; - - typedef typename mpl::if_< - is_reference< result_type > - , typename mpl::if_< - is_const< cv_value_type > - , readable_lvalue_iterator_tag - , writable_lvalue_iterator_tag - >::type - , readable_iterator_tag - >::type maximum_access_tag; - - typedef typename minimum_category< - maximum_access_tag - , typename access_category::type - >::type access_category; - - public: - typedef iterator_adaptor< - transform_iterator - , Iterator - , cv_value_type - , access_category - , result_type - > type; + public: + typedef iterator_adaptor< + transform_iterator + , Iterator + , cv_value_type + , use_default // Leave the traversal category alone + , reference + > type; }; } @@ -150,12 +137,16 @@ namespace boost return transform_iterator(it, fun); } + // Version which allows explicit specification of the UnaryFunction + // type. + // + // This generator is not provided if UnaryFunction is a function + // pointer type, because it's too dangerous: the default-constructed + // function pointer in the iterator be 0, leading to a runtime + // crash. template - // don't provide this generator if UnaryFunction is a - // function pointer type. Too dangerous. We should probably - // find a cheaper test than is_class<> typename iterators::enable_if< - is_class + is_class // We should probably find a cheaper test than is_class<> , transform_iterator >::type make_transform_iterator(Iterator it) @@ -174,4 +165,6 @@ namespace boost } // namespace boost +#include + #endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP diff --git a/include/boost/iterator/zip_iterator.hpp b/include/boost/iterator/zip_iterator.hpp index 943a347..f48ee53 100755 --- a/include/boost/iterator/zip_iterator.hpp +++ b/include/boost/iterator/zip_iterator.hpp @@ -28,6 +28,8 @@ #include #include +#include + #include #if BOOST_WORKAROUND(__GNUC__, == 2) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) @@ -259,16 +261,17 @@ namespace boost { ) { typedef typename tuple_meta_transform< - typename Tuple::tail_type + BOOST_DEDUCED_TYPENAME Tuple::tail_type , Fun >::type transformed_tail_type; return tuples::cons< - typename mpl::apply1::type + BOOST_DEDUCED_TYPENAME mpl::apply1< + Fun, BOOST_DEDUCED_TYPENAME Tuple::head_type + >::type , transformed_tail_type >( - f(boost::tuples::get<0>(t)), - tuple_transform(t.get_tail(), f) + f(boost::tuples::get<0>(t)), tuple_transform(t.get_tail(), f) ); } @@ -380,12 +383,12 @@ namespace boost { { typedef typename tuple_impl_specific::tuple_meta_transform< IteratorTuple - , traversal_category + , iterator_traversal<> >::type tuple_of_traversal_tags; typedef typename tuple_impl_specific::tuple_meta_accumulate< tuple_of_traversal_tags - , minimum_category + , minimum_category<> , random_access_traversal_tag >::type type; }; @@ -398,31 +401,6 @@ namespace boost { }; #endif - template - struct iterator_is_readable - : is_tag< - readable_iterator_tag - , typename access_category::type - > - { - BOOST_MPL_AUX_LAMBDA_SUPPORT(1, iterator_is_readable, (Iterator)) - }; - -# ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT - // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work - // out well. Instantiating the nested apply template also - // requires instantiating iterator_traits on the - // placeholder. Instead we just specialize it as a metafunction - // class. - template <> - struct iterator_is_readable - { - template - struct apply : iterator_is_readable - {}; - }; -# endif - // We need to call tuple_meta_accumulate with mpl::and_ as the // accumulating functor. To this end, we need to wrap it into // a struct that has exactly two arguments (that is, template @@ -446,28 +424,6 @@ namespace boost { }; # endif - // Metafunction to assert that all iterators in a tuple are - // readable. - // - // Probably not worth it, IMO. Why not a writable zip_iterator - // anyway? -- dwa. - // - template - struct all_iterators_in_tuple_readable - { - - typedef typename tuple_impl_specific::tuple_meta_transform< - IteratorTuple, - iterator_is_readable - >::type tuple_of_readability_bools; - - typedef typename tuple_impl_specific::tuple_meta_accumulate< - tuple_of_readability_bools, - and_with_two_args - , mpl::bool_ - >::type type; - }; - /////////////////////////////////////////////////////////////////// // // Class zip_iterator_base @@ -479,14 +435,6 @@ namespace boost { struct zip_iterator_base { private: -#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - // seems to give vc7's parser fits, and vc6 needs help here too - BOOST_STATIC_ASSERT( - detail::all_iterators_in_tuple_readable< - IteratorTuple - >::type::value - ); -#endif // Reference type is the type of the tuple obtained from the // iterators' reference types. typedef typename @@ -506,11 +454,6 @@ namespace boost { detail::minimum_traversal_category_in_iterator_tuple< IteratorTuple >::type traversal_category; - - // Access category is readable_iterator_tag. It has been - // asserted that all iterators in the tuple are readable. - typedef readable_iterator_tag access_category; - public: // The iterator facade type from which the zip iterator will @@ -518,7 +461,6 @@ namespace boost { typedef iterator_facade< zip_iterator, value_type, - access_category, traversal_category, reference, difference_type @@ -616,7 +558,7 @@ namespace boost { { detail::tuple_impl_specific::tuple_for_each( m_iterator_tuple, - detail::advance_iterator(n) + detail::advance_iterator(n) ); } // Incrementing a zip iterator means to increment all iterators in diff --git a/test/Jamfile b/test/Jamfile index 1a7b9a1..94a46d3 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -18,6 +18,8 @@ test-suite iterator # compilation problems. [ run is_convertible_fail.cpp ] + [ run zip_iterator_test.cpp ] + # These tests should work for just about everything. [ compile is_lvalue_iterator.cpp ] [ compile is_readable_iterator.cpp ] @@ -34,8 +36,6 @@ test-suite iterator [ run counting_iterator_test.cpp ] [ run permutation_iterator_test.cpp : : : # on ] - [ compile iterator_categories.cpp ] - [ run zip_iterator_test.cpp ] [ run ../../utility/iterator_adaptor_examples.cpp ] [ run ../../utility/counting_iterator_example.cpp ] diff --git a/test/concept_tests.cpp b/test/concept_tests.cpp index 5370f76..399911d 100644 --- a/test/concept_tests.cpp +++ b/test/concept_tests.cpp @@ -5,15 +5,16 @@ // to its suitability for any purpose. #include +#include #include -#include // remove -#include -#include "static_assert_same.hpp" // remove + +struct new_random_access + : std::random_access_iterator_tag + , boost::random_access_traversal_tag +{}; struct new_iterator - : public boost::iterator< boost::iterator_tag< - boost::writable_lvalue_iterator_tag - , boost::random_access_traversal_tag>, int> + : public boost::iterator< new_random_access, int > { int& operator*() const { return *m_x; } new_iterator& operator++() { return *this; } @@ -52,103 +53,13 @@ struct old_iterator }; old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; } -struct my_writable_lvalue_iterator_tag -{ - operator boost::writable_lvalue_iterator_tag() const; -}; - -struct my_single_pass_traversal_tag -{ - operator boost::single_pass_traversal_tag() const; -}; - -void test_tag_convertibility() -{ - // This set of tests is by no means complete. - - // Test that this is an input/output iterator -#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) - { - typedef boost::iterator_tag< - boost::writable_lvalue_iterator_tag - , boost::single_pass_traversal_tag - > tag; - - BOOST_STATIC_ASSERT(( - boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - !boost::is_convertible::value - )); - } - - // Test that it's possible to build new sub-tags without - // derivation. Convertibility should be enough - { - typedef boost::iterator_tag< - my_writable_lvalue_iterator_tag - , my_single_pass_traversal_tag - > tag; - - BOOST_STATIC_ASSERT(( - boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - !boost::is_convertible::value - )); - } - - // Test that a single-pass readable lvalue iterator is only an - // input iterator. Requires special case handling in - // categories.hpp - { - typedef boost::iterator_tag< - boost::readable_lvalue_iterator_tag - , boost::single_pass_traversal_tag - > tag; - BOOST_STATIC_ASSERT(( - boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - !boost::is_convertible::value - )); - BOOST_STATIC_ASSERT(( - !boost::is_convertible::value - )); - } -#endif -} - int main() { - test_tag_convertibility(); - - 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)); - int test = static_assert_same::value; - test = static_assert_same::value; - - // BOOST_STATIC_ASSERT((boost::detail::is_random_access_iterator::value)); - test = static_assert_same::value; - test = static_assert_same::value; - - typedef boost::traversal_category::type traversal_category; - - // BOOST_STATIC_ASSERT(boost::detail::has_traversal::value); - BOOST_STATIC_ASSERT(boost::detail::is_new_iterator_tag::value); - - - test = static_assert_same::value; - (void)test; - + boost::iterator_traversal::type tc; + boost::random_access_traversal_tag derived = tc; + (void)derived; + boost::function_requires< boost_concepts::WritableLvalueIteratorConcept >(); boost::function_requires< diff --git a/test/counting_iterator_test.cpp b/test/counting_iterator_test.cpp index fbfe70b..73f69f9 100644 --- a/test/counting_iterator_test.cpp +++ b/test/counting_iterator_test.cpp @@ -286,7 +286,7 @@ int main() # 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)); diff --git a/test/filter_iterator_test.cpp b/test/filter_iterator_test.cpp index a00af95..edf3ccf 100644 --- a/test/filter_iterator_test.cpp +++ b/test/filter_iterator_test.cpp @@ -7,13 +7,12 @@ #include #include #include -#include +#include #include #include using boost::dummyT; -BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) struct one_or_four { @@ -38,12 +37,12 @@ int main() filter_iter(one_or_four(), array, array+N) , dummyT(1), dummyT(4)); - BOOST_STATIC_ASSERT(( - !boost::detail::is_tag< - boost::random_access_traversal_tag - , boost::traversal_category::type - >::value - )); + BOOST_STATIC_ASSERT( + (!boost::is_convertible< + boost::iterator_traversal::type + , boost::random_access_traversal_tag + >::value + )); //# endif diff --git a/test/indirect_iterator_test.cpp b/test/indirect_iterator_test.cpp index 3f28948..cad4091 100644 --- a/test/indirect_iterator_test.cpp +++ b/test/indirect_iterator_test.cpp @@ -46,8 +46,7 @@ struct my_iterator_tag : public std::random_access_iterator_tag { }; using boost::dummyT; -BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) -BOOST_TT_BROKEN_COMPILER_SPEC(boost::shared_ptr) +BOOST_TT_BROKEN_COMPILER_SPEC(boost::shared_ptr) typedef std::vector storage; typedef std::vector pointer_ra_container; diff --git a/test/is_lvalue_iterator.cpp b/test/is_lvalue_iterator.cpp index 9c23c9c..fdace52 100755 --- a/test/is_lvalue_iterator.cpp +++ b/test/is_lvalue_iterator.cpp @@ -32,12 +32,15 @@ struct noncopyable_iterator : boost::iterator +template +struct proxy_iterator + : boost::iterator { + typedef T value_type; + #if BOOST_WORKAROUND(__GNUC__, == 2) - typedef boost::iterator base; + typedef boost::iterator base; typedef base::iterator_category iterator_category; - typedef base::value_type value_type; typedef base::difference_type difference_type; typedef base::pointer pointer; typedef base::reference reference; @@ -45,14 +48,43 @@ struct proxy_iterator : boost::iterator struct proxy { - operator v&() const; - proxy& operator=(v) const; + operator value_type&() const; + proxy& operator=(value_type) const; }; proxy operator*() const; }; -BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy) +template +struct lvalue_iterator +{ + typedef T value_type; + typedef T& reference; + typedef T difference_type; + typedef std::input_iterator_tag iterator_category; + typedef T* pointer; + + T& operator*() const; + lvalue_iterator& operator++(); + lvalue_iterator operator++(int); +}; + +template +struct constant_lvalue_iterator +{ + typedef T value_type; + typedef T const& reference; + typedef T difference_type; + typedef std::input_iterator_tag iterator_category; + typedef T const* pointer; + + T const& operator*() const; + constant_lvalue_iterator& operator++(); + constant_lvalue_iterator operator++(int); +}; + +BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy) +BOOST_TT_BROKEN_COMPILER_SPEC(proxy_iterator::proxy) int main() { @@ -62,7 +94,8 @@ int main() BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::const_iterator>::value); BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator > >::value); BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator >::value); - BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator >::value); #ifndef BOOST_NO_LVALUE_RETURN_DETECTION BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator::value); #endif @@ -70,18 +103,43 @@ int main() // reference binding BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + - BOOST_STATIC_ASSERT(boost::is_mutable_lvalue_iterator::value); - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value); - BOOST_STATIC_ASSERT(boost::is_mutable_lvalue_iterator::iterator>::value); - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::const_iterator>::value); - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator > >::value); - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator >::value); - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + + + + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator::iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::const_iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator > >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); #ifndef BOOST_NO_LVALUE_RETURN_DETECTION - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::value); #endif - BOOST_STATIC_ASSERT(!boost::is_mutable_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::value); + + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); +#endif + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); + + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); return 0; } diff --git a/test/iterator_adaptor_test.cpp b/test/iterator_adaptor_test.cpp index 79b9001..961895f 100644 --- a/test/iterator_adaptor_test.cpp +++ b/test/iterator_adaptor_test.cpp @@ -14,6 +14,10 @@ #include #include +#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) +# include +# include +#endif #include # include @@ -26,7 +30,7 @@ #include "static_assert_same.hpp" -struct my_iterator_tag : public std::random_access_iterator_tag { }; +#include using boost::dummyT; @@ -83,7 +87,7 @@ struct ptr_iterator ptr_iterator , V* , V - , std::random_access_iterator_tag + , boost::random_access_traversal_tag #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) , V& #endif @@ -94,7 +98,7 @@ private: ptr_iterator , V* , V - , std::random_access_iterator_tag + , boost::random_access_traversal_tag #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) , V& #endif @@ -114,13 +118,13 @@ public: }; // Non-functional iterator for category modification checking -template -struct modify_category +template +struct modify_traversal : boost::iterator_adaptor< - modify_category + modify_traversal , Iter , boost::use_default - , Category + , Traversal > {}; @@ -179,6 +183,33 @@ struct constant_iterator : base_t(it) {} }; +char (& traversal2(boost::incrementable_traversal_tag) )[1]; +char (& traversal2(boost::single_pass_traversal_tag ) )[2]; +char (& traversal2(boost::forward_traversal_tag ) )[3]; +char (& traversal2(boost::bidirectional_traversal_tag) )[4]; +char (& traversal2(boost::random_access_traversal_tag) )[5]; + +template +struct traversal3 +{ + static typename boost::iterator_category_to_traversal::type x; + BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(traversal2(x))); + typedef char (&type)[value]; +}; + +template +typename traversal3::type traversal(Cat); + +template +int static_assert_traversal(Iter* = 0, Trav* = 0) +{ + typedef typename boost::iterator_category_to_traversal< + BOOST_DEDUCED_TYPENAME Iter::iterator_category + >::type t2; + + return static_assert_same::value; +} + int main() { @@ -219,7 +250,17 @@ main() typedef ptr_iterator Iter1; test = static_assert_same::value; test = static_assert_same::value; - test = static_assert_same::value; test = static_assert_same::value; + +#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + BOOST_STATIC_ASSERT(boost::is_readable_iterator::value); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); +# endif +#endif + +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness + test = static_assert_same::value; +#endif } { @@ -229,19 +270,19 @@ main() test = static_assert_same::value; test = static_assert_same::value; +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) // borland drops constness test = static_assert_same::value; +#endif - test = static_assert_same::value; - test = static_assert_same::value; - - // Test category modification - typedef modify_category ReadableIter; - test = static_assert_same::value; - - typedef modify_category IncrementableIter; - test = static_assert_same::value; - test = static_assert_same::value; +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); +#endif + + typedef modify_traversal IncrementableIter; + static_assert_traversal(); + static_assert_traversal(); } // Test the iterator_adaptor diff --git a/test/iterator_archetype_cc.cpp b/test/iterator_archetype_cc.cpp index 1edf5e5..b5badea 100644 --- a/test/iterator_archetype_cc.cpp +++ b/test/iterator_archetype_cc.cpp @@ -12,14 +12,15 @@ int main() { - { - typedef boost::iterator_archetype iter; + typedef boost::iterator_archetype< + int + , boost::iterator_archetypes::writable_lvalue_iterator_t + , boost::random_access_traversal_tag + > iter; boost::function_requires< boost_concepts::WritableLvalueIteratorConcept >(); boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); - } - return 0; // keep msvc happy + + return 0; // keep msvc happy } diff --git a/test/iterator_categories.cpp b/test/iterator_categories.cpp deleted file mode 100755 index e36f2c9..0000000 --- a/test/iterator_categories.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright David Abrahams 2003. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include - -using namespace boost; - -// Utility function which converts an iterator_category into a -// traversal tag -template -typename iterator_category_to_traversal::type c2t(C) -{ - typedef typename iterator_category_to_traversal::type result; - return result(); -} - -struct v -{ - v(); - ~v(); -}; - -// -// Test conversions from iterator_tag<...> to old-style iterator categories -// - -// These "solid" tag types ensure exact matching of iterator -// classification, because unlike the std:: iterator tags, they're not -// inter-convertible -struct output_iter {}; -struct input_iter {}; -struct input_output_iter {}; -struct forward_iter {}; -struct bidirectional_iter {}; -struct random_access_iter{} ; - -// Convert various old-style categories into "solid" tags. -input_iter cat(std::input_iterator_tag); -output_iter cat(std::output_iterator_tag); -input_output_iter cat(boost::detail::input_output_iterator_tag); -forward_iter cat(std::forward_iterator_tag); -bidirectional_iter cat(std::bidirectional_iterator_tag); -random_access_iter cat(std::random_access_iterator_tag); - -random_access_iter x1 = cat(iterator_tag()); -random_access_iter x2 = cat(iterator_tag()); -bidirectional_iter x3 = cat(iterator_tag()); -forward_iter x4 = cat(iterator_tag()); -input_output_iter x5 = cat(iterator_tag()); -input_iter x6 = cat(iterator_tag()); -output_iter x7 = cat(iterator_tag()); - - -// -// Test conversion from old-style iterator categories to traversal categories -// - -// These "solid" tag types ensure exact matching of iterator -// classification, because unlike the traversal tags, they're not -// inter-convertible -struct incrementable_traversal {}; -struct single_pass_traversal {}; -struct forward_traversal {}; -struct bidirectional_traversal {}; -struct random_access_traversal {} ; - -// Convert various traversal categories into "solid" tags -incrementable_traversal trav(incrementable_traversal_tag); -single_pass_traversal trav(single_pass_traversal_tag); -forward_traversal trav(forward_traversal_tag); -bidirectional_traversal trav(bidirectional_traversal_tag); -random_access_traversal trav(random_access_traversal_tag); - -// Show that full types of tags that are already traversal categories -// are preserved -iterator_tag yz1 - = c2t(iterator_tag()); - -// Test traversal extraction from both old-style and new-style tags -random_access_traversal yy1 = trav(c2t(iterator_tag())); -bidirectional_traversal yy2 = trav(c2t(iterator_tag())); -forward_traversal yy3 = trav(c2t(iterator_tag())); -single_pass_traversal yy4 = trav(c2t(iterator_tag())); -incrementable_traversal yy5 = trav(c2t(iterator_tag())); - -random_access_traversal z1 = trav(c2t(std::random_access_iterator_tag())); -bidirectional_traversal z2 = trav(c2t(std::bidirectional_iterator_tag())); -forward_traversal z3 = trav(c2t(std::forward_iterator_tag())); -single_pass_traversal z4 = trav(c2t(std::input_iterator_tag())); -incrementable_traversal z5 = trav(c2t(std::output_iterator_tag())); diff --git a/test/reverse_iterator_test.cpp b/test/reverse_iterator_test.cpp index cb069cd..62e1454 100644 --- a/test/reverse_iterator_test.cpp +++ b/test/reverse_iterator_test.cpp @@ -11,8 +11,6 @@ using boost::dummyT; -BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) - // Test reverse iterator int main() { diff --git a/test/static_assert_same.hpp b/test/static_assert_same.hpp index 3bff6bf..e463192 100644 --- a/test/static_assert_same.hpp +++ b/test/static_assert_same.hpp @@ -10,13 +10,17 @@ #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template -struct static_assert_same; +struct static_assert_same_base; template -struct static_assert_same +struct static_assert_same_base { enum { value = 1 }; }; + +template +struct static_assert_same : static_assert_same_base {}; + #else # include # include diff --git a/test/transform_iterator_test.cpp b/test/transform_iterator_test.cpp index cc73846..f044add 100644 --- a/test/transform_iterator_test.cpp +++ b/test/transform_iterator_test.cpp @@ -184,17 +184,14 @@ main() for (int k2 = 0; k2 < N; ++k2) x[k2] = x[k2] * 2; - boost::input_iterator_test(boost::make_transform_iterator(y, mult_2) - , x[0] - , x[1]); + boost::input_iterator_test( + boost::make_transform_iterator(y, mult_2), x[0], x[1]); - boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_2) - , x[0] - , x[1]); + boost::input_iterator_test( + boost::make_transform_iterator(&y[0], mult_2), x[0], x[1]); - boost::random_access_readable_iterator_test(boost::make_transform_iterator(y, mult_2) - , N - , x); + boost::random_access_readable_iterator_test( + boost::make_transform_iterator(y, mult_2), N, x); } @@ -213,25 +210,34 @@ main() } - std::copy(x, - x + N, - boost::make_transform_iterator((pair_t*)values, select_first())); + std::copy( + x + , x + N + , boost::make_transform_iterator((pair_t*)values, select_first()) + ); - std::copy(y, - y + N, - boost::make_transform_iterator((pair_t*)values, select_second())); + std::copy( + y + , y + N + , boost::make_transform_iterator((pair_t*)values, select_second()) + ); - boost::random_access_readable_iterator_test(boost::make_transform_iterator((pair_t*)values, value_select_first()), - N, - x); + boost::random_access_readable_iterator_test( + boost::make_transform_iterator((pair_t*)values, value_select_first()) + , N + , x + ); - boost::random_access_readable_iterator_test(boost::make_transform_iterator((pair_t*)values, const_select_first()), - N, - x); + boost::random_access_readable_iterator_test( + boost::make_transform_iterator((pair_t*)values, const_select_first()) + , N, x + ); - boost::constant_lvalue_iterator_test(boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]); + boost::constant_lvalue_iterator_test( + boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]); - boost::mutable_lvalue_iterator_test(boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17); + boost::non_const_lvalue_iterator_test( + boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17); } diff --git a/test/unit_tests.cpp b/test/unit_tests.cpp index ed6c279..c4077eb 100644 --- a/test/unit_tests.cpp +++ b/test/unit_tests.cpp @@ -5,9 +5,12 @@ // to its suitability for any purpose. #include #include + #include "static_assert_same.hpp" + #include +#include struct X { int a; }; @@ -40,29 +43,32 @@ void category_test() using namespace boost::detail; BOOST_STATIC_ASSERT(( - !is_tag< - input_output_iterator_tag - , std::input_iterator_tag>::value)); - - BOOST_STATIC_ASSERT(( - !is_tag< - input_output_iterator_tag - , std::output_iterator_tag>::value)); - - BOOST_STATIC_ASSERT(( - is_tag< + !boost::is_convertible< std::input_iterator_tag , input_output_iterator_tag>::value)); BOOST_STATIC_ASSERT(( - is_tag< + !boost::is_convertible< std::output_iterator_tag , input_output_iterator_tag>::value)); - + BOOST_STATIC_ASSERT(( - is_tag< + boost::is_convertible< input_output_iterator_tag - , std::forward_iterator_tag>::value)); + , std::input_iterator_tag>::value)); + + BOOST_STATIC_ASSERT(( + boost::is_convertible< + input_output_iterator_tag + , std::output_iterator_tag>::value)); + +#if 0 // This seems wrong; we're not advertising + // input_output_iterator_tag are we? + BOOST_STATIC_ASSERT(( + boost::is_convertible< + std::forward_iterator_tag + , input_output_iterator_tag>::value)); +#endif int test = static_assert_min_cat< std::input_iterator_tag,input_output_iterator_tag, std::input_iterator_tag @@ -72,9 +78,11 @@ void category_test() input_output_iterator_tag,std::input_iterator_tag, std::input_iterator_tag >::value; +#if 0 test = static_assert_min_cat< input_output_iterator_tag,std::forward_iterator_tag, input_output_iterator_tag >::value; +#endif test = static_assert_min_cat< std::input_iterator_tag,std::forward_iterator_tag, std::input_iterator_tag @@ -84,29 +92,13 @@ void category_test() std::input_iterator_tag,std::random_access_iterator_tag, std::input_iterator_tag >::value; +#if 0 // This would be wrong: a random access iterator is not + // neccessarily writable, as is an output iterator. test = static_assert_min_cat< std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag >::value; +#endif - BOOST_STATIC_ASSERT((is_traversal_tag< incrementable_traversal_tag >::value)); - BOOST_STATIC_ASSERT((is_traversal_tag< single_pass_traversal_tag >::value)); - BOOST_STATIC_ASSERT((is_traversal_tag< forward_traversal_tag >::value)); - BOOST_STATIC_ASSERT((is_traversal_tag< bidirectional_traversal_tag >::value)); - BOOST_STATIC_ASSERT((is_traversal_tag< random_access_traversal_tag >::value)); - - BOOST_STATIC_ASSERT((!is_traversal_tag< std::input_iterator_tag >::value)); - BOOST_STATIC_ASSERT((!is_traversal_tag< readable_iterator_tag >::value)); - - BOOST_STATIC_ASSERT((is_access_tag< readable_iterator_tag >::value)); - BOOST_STATIC_ASSERT((is_access_tag< writable_iterator_tag >::value)); - BOOST_STATIC_ASSERT((is_access_tag< swappable_iterator_tag >::value)); - BOOST_STATIC_ASSERT((is_access_tag< readable_writable_iterator_tag >::value)); - BOOST_STATIC_ASSERT((is_access_tag< readable_lvalue_iterator_tag >::value)); - BOOST_STATIC_ASSERT((is_access_tag< writable_lvalue_iterator_tag >::value)); - - BOOST_STATIC_ASSERT((!is_access_tag< std::input_iterator_tag >::value)); - BOOST_STATIC_ASSERT((!is_access_tag< incrementable_traversal_tag >::value)); - (void)test; } diff --git a/test/zip_iterator_test.cpp b/test/zip_iterator_test.cpp index d6fcc2b..f33dbd9 100755 --- a/test/zip_iterator_test.cpp +++ b/test/zip_iterator_test.cpp @@ -48,32 +48,18 @@ #include #include #include +#include #include #include #include -// Uncomment to see static assert. -// #define PROVOKE_STATIC_ASSERT - -///////////////////////////////////////////////////////////////////////////// -// -// Fake iterator for testing zip iterator categories -// -///////////////////////////////////////////////////////////////////////////// - -class fake_writable_iterator -{ -public: - typedef int& reference; - typedef int value_type; - typedef int* pointer; - typedef ptrdiff_t difference_type; - typedef boost::iterator_tag< - boost::writable_iterator_tag, - boost::forward_traversal_tag - > iterator_category; -}; - +template +struct pure_traversal + : boost::detail::pure_traversal_tag< + typename boost::iterator_traversal::type + > +{}; + ///////////////////////////////////////////////////////////////////////////// // // Das Main Funktion @@ -871,25 +857,15 @@ int main( void ) // The big iterator of the previous test has vector, list, and set iterators. // Therefore, it must be bidirectional, but not random access. - bool bBigItIsBidirectionalIterator = boost::is_same< - boost::bidirectional_traversal_tag, - boost::traversal_category::type - >::value; - // - bool bBigItIsRandomAccessIterator = boost::is_same< - boost::random_access_traversal_tag, - boost::traversal_category::type - >::value; - // - bool bBigItIsReadableIterator = boost::is_same< - boost::readable_iterator_tag, - boost::access_category::type - >::value; - // - bool bBigItIsReadableLValueIterator = boost::is_same< - boost::readable_lvalue_iterator_tag, - boost::access_category::type - >::value; + bool bBigItIsBidirectionalIterator = boost::is_convertible< + boost::iterator_traversal::type + , boost::bidirectional_traversal_tag + >::value; + + bool bBigItIsRandomAccessIterator = boost::is_convertible< + boost::iterator_traversal::type + , boost::random_access_traversal_tag + >::value; // A combining iterator with all vector iterators must have random access // traversal. @@ -901,63 +877,15 @@ int main( void ) > > all_vects_type; - bool bAllVectsIsRandomAccessIterator = boost::is_same< - boost::random_access_traversal_tag, - boost::traversal_category::type + bool bAllVectsIsRandomAccessIterator = boost::is_convertible< + boost::iterator_traversal::type + , boost::random_access_traversal_tag >::value; - // - bool bAllVectsIsReadableIterator = boost::is_same< - boost::readable_iterator_tag, - boost::access_category::type - >::value; - // - bool bAllVectsIsReadableLValueIterator = boost::is_same< - boost::readable_lvalue_iterator_tag, - boost::access_category::type - >::value; - - // Test if the meta function all_iterators_readable, which is used - // for compile-time asserting, works. - // - bool bAllIteratorsReadable1 = - boost::detail::all_iterators_in_tuple_readable< - boost::tuples::tuple< - std::vector::const_iterator, - std::set::iterator - > - >::type::value; - - bool bAllIteratorsReadable2 = - boost::detail::all_iterators_in_tuple_readable< - boost::tuples::tuple< - std::vector::const_iterator, - fake_writable_iterator, - std::set::iterator - > - >::type::value; - - // Compile-time assert because of non-readable iterator. - // -#ifdef PROVOKE_STATIC_ASSERT - typedef boost::zip_iterator< - boost::tuples::tuple< - fake_writable_iterator - > - >no_compile_type; - - no_compile_type no_compile; -#endif // The big test. if( bBigItIsBidirectionalIterator && ! bBigItIsRandomAccessIterator && - bBigItIsReadableIterator && - ! bBigItIsReadableLValueIterator && - bAllVectsIsRandomAccessIterator && - ! bAllVectsIsReadableLValueIterator && - bAllVectsIsReadableIterator && - bAllIteratorsReadable1 && - ! bAllIteratorsReadable2 + bAllVectsIsRandomAccessIterator ) { ++num_successful_tests; @@ -977,6 +905,6 @@ int main( void ) << "\nNumber of failed tests: " << static_cast(num_failed_tests) << std::endl; - return 0; + return num_failed_tests; }