diff --git a/include/boost/iterator/detail/categories.hpp b/include/boost/iterator/detail/categories.hpp index 167100a..841ac4c 100644 --- a/include/boost/iterator/detail/categories.hpp +++ b/include/boost/iterator/detail/categories.hpp @@ -1,335 +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 - -# 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 - // - enum iterator_access - { - readable_iterator = 1 - , writable_iterator = 2 - , swappable_iterator = 4 - , lvalue_iterator = 8 - }; - - // - // 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 - { - template - struct access_c : mpl::integral_c - {}; - - - // - // 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 - - // If TraversalTag is convertible to Known, return it, otherwise - // return the result of invoking NullaryElse - template - struct known_traversal_tag - : mpl::apply_if< - is_convertible - , mpl::identity - , NullaryElse - > - {}; - - template - struct max_known_traversal_tag - : known_traversal_tag< - Tag, random_access_traversal_tag - , known_traversal_tag< - Tag, bidirectional_traversal_tag - , known_traversal_tag< - Tag, forward_traversal_tag - , known_traversal_tag< - Tag, single_pass_traversal_tag - , known_traversal_tag< - Tag, incrementable_traversal_tag - , error_iterator_tag - > - > - > - > - > - {}; - - template - struct known_access_tag - : mpl::apply_if_c< - ((AccessTag::value & Known) == Known) - , mpl::identity > - , NullaryElse - > - {}; - - - // 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_access_tag< - Tag, (writable_iterator|readable_iterator|swappable_iterator|lvalue_iterator) - , known_access_tag< - Tag, (readable_iterator|lvalue_iterator) - , known_access_tag< - Tag, (writable_iterator|readable_iterator|swappable_iterator) - , known_access_tag< - Tag, writable_iterator - , known_access_tag< - Tag, readable_iterator - , mpl::apply_if_c< - (swappable_iterator & Tag::value) - , 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 - - } // namespace detail - -} // namespace boost - -#include - -#endif // BOOST_ITERATOR_DETAIL_CATEGORIES_HPP +#error obsolete diff --git a/include/boost/iterator/iterator_categories.hpp b/include/boost/iterator/iterator_categories.hpp index eedeee0..7388ea9 100644 --- a/include/boost/iterator/iterator_categories.hpp +++ b/include/boost/iterator/iterator_categories.hpp @@ -4,411 +4,195 @@ // "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 +# include # include -#endif +# 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 +# include +# include namespace boost { - namespace detail +// +// Traversal Categories +// +struct incrementable_traversal_tag {}; + +struct single_pass_traversal_tag + : incrementable_traversal_tag {}; + +struct forward_traversal_tag + : single_pass_traversal_tag {}; + +struct bidirectional_traversal_tag + : forward_traversal_tag {}; + +struct random_access_traversal_tag + : bidirectional_traversal_tag {}; + +namespace detail +{ + struct input_output_iterator_tag + : std::input_iterator_tag, std::output_iterator_tag {}; + + template + struct old_iterator_category { - // 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 - : access_c {}; - - }; - - template <> - struct std_to_new_tags - { - typedef incrementable_traversal_tag type; - - template - struct apply - : access_c {}; - }; - - template <> - struct std_to_new_tags - { - typedef forward_traversal_tag type; - - template - struct apply - : mpl::if_< - python::detail::is_reference_to_const - , access_c<(readable_iterator|lvalue_iterator)> - , access_c<(readable_iterator|writable_iterator|lvalue_iterator)> - > - {}; - }; - - 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< - // Take the category down to its most-refined known - // std::tag, in case of derivation/convertibility - typename std_category::type - > - { - }; - - template - struct old_tag_to_traversal - : old_tag_converter - {}; - - - template - struct old_tag_to_access - : mpl::apply1< - old_tag_converter - , Reference - > - {}; - -# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) - // Deal with ETI - template <> struct old_tag_to_access {}; - template <> struct old_tag_converter {}; -# 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 - - namespace detail { - - template - struct new_tag_to_traversal - { - typedef typename NewCategoryTag::traversal type; - }; - - template - struct new_tag_to_access - { - typedef typename NewCategoryTag::access_type type; - }; -#if 0 // what was this all about? - template - struct new_tag_to_access - : mpl::apply_if< - python::detail::is_reference_to_const - , remove_access_writability - , mpl::identity - > - {}; -#endif - - template - struct tag_access_category - : mpl::apply_if< - is_new_iterator_tag - , new_tag_to_access - , old_tag_to_access - > - { - }; - - template - struct tag_traversal_category - : mpl::apply_if< - is_new_iterator_tag - , new_tag_to_traversal - , old_tag_to_traversal - > - { - }; - -# if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) - // Deal with ETI - template <> struct tag_access_category { typedef void type; }; - template <> struct tag_traversal_category { 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 + typedef typename mpl:: +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + if_ +# else + apply_if # endif + < + 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 + > + > +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + ::type +# endif + , typename mpl::apply_if< + mpl::and_< + is_convertible + , is_convertible + > + , mpl::if_< + is_const + , std::input_iterator_tag + , input_output_iterator_tag + > + , mpl::identity + > +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + ::type +# endif + >::type type; + }; - // 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< - access_c<(readable_iterator|lvalue_iterator)> - , single_pass_traversal_tag - > - { - typedef std::input_iterator_tag type; - }; - - } // namespace detail - - template - struct access_category - : detail::tag_access_category< - typename detail::iterator_traits::iterator_category - , typename detail::iterator_traits::reference + // + // 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_style_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 + > + > + > + > > {}; + +} // namespace detail - template - struct traversal_category - : detail::tag_traversal_category< - typename detail::iterator_traits::iterator_category - > - { - }; + +// +// 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_style_category_to_traversal + > +{}; + +// +// To be used for a new-style iterator's iterator_category; provides +// implicit conversion to the appropriate old-style iterator category. +// +// If Value is const 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_tag + : detail::old_iterator_category::type +{ + operator Traversal() { return Traversal(); } +# if 0 + typedef typename detail::old_iterator_category< + Value, Reference, Traversal + >::type old_category; + + operator old_category() const { return old_category(); } +# endif +}; + +// 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. - 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 - , detail::access_c<(readable_iterator|lvalue_iterator)> - , detail::access_c<(readable_iterator|writable_iterator|lvalue_iterator)> - > - { - }; - - 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::value - , typename detail::max_known_traversal_tag::type - >::type - { - typedef detail::access_c<(Access & ~lvalue_iterator)> access_type; - BOOST_STATIC_CONSTANT(iterator_access, value = (iterator_access)(Access & ~lvalue_iterator)); - typedef TraversalTag traversal; - }; - - namespace detail - { -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// 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_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