194 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			194 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | // 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 <boost/iterator/iterator_categories.hpp> | ||
|  | 
 | ||
|  | # include <boost/mpl/or.hpp>  // used in iterator_tag inheritance logic | ||
|  | # include <boost/mpl/and.hpp> | ||
|  | # include <boost/mpl/if.hpp> | ||
|  | # include <boost/mpl/eval_if.hpp> | ||
|  | # include <boost/mpl/identity.hpp> | ||
|  | # include <boost/mpl/assert.hpp> | ||
|  | 
 | ||
|  | # include <boost/type_traits/is_same.hpp> | ||
|  | # include <boost/type_traits/is_const.hpp> | ||
|  | # include <boost/type_traits/is_reference.hpp> | ||
|  | # include <boost/type_traits/is_convertible.hpp> | ||
|  | 
 | ||
|  | # include <boost/type_traits/is_same.hpp> | ||
|  | 
 | ||
|  | # include <boost/iterator/detail/config_def.hpp> // try to keep this last | ||
|  | 
 | ||
|  | # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY | ||
|  | #  include <boost/detail/indirect_traits.hpp> | ||
|  | # endif | ||
|  | 
 | ||
|  | // | ||
|  | // iterator_category deduction for iterator_facade | ||
|  | // | ||
|  | 
 | ||
|  | namespace boost { | ||
|  | namespace iterators { | ||
|  | 
 | ||
|  | // forward declaration | ||
|  | struct use_default; | ||
|  | 
 | ||
|  | 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 <class ValueParam, class Reference> | ||
|  | struct iterator_writability_disabled | ||
|  | # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic? | ||
|  |   : mpl::or_< | ||
|  |         is_const<Reference> | ||
|  |       , boost::detail::indirect_traits::is_reference_to_const<Reference> | ||
|  |       , is_const<ValueParam> | ||
|  |     > | ||
|  | # else | ||
|  |   : is_const<ValueParam> | ||
|  | # endif | ||
|  | {}; | ||
|  | 
 | ||
|  | 
 | ||
|  | // | ||
|  | // Convert an iterator_facade's traversal category, Value parameter, | ||
|  | // and ::reference type to an appropriate old-style category. | ||
|  | // | ||
|  | // Due to changeset 21683, this now never results in a category convertible | ||
|  | // to output_iterator_tag. | ||
|  | // | ||
|  | // Change at: https://svn.boost.org/trac/boost/changeset/21683 | ||
|  | template <class Traversal, class ValueParam, class Reference> | ||
|  | struct iterator_facade_default_category | ||
|  |   : mpl::eval_if< | ||
|  |         mpl::and_< | ||
|  |             is_reference<Reference> | ||
|  |           , is_convertible<Traversal,forward_traversal_tag> | ||
|  |         > | ||
|  |       , mpl::eval_if< | ||
|  |             is_convertible<Traversal,random_access_traversal_tag> | ||
|  |           , mpl::identity<std::random_access_iterator_tag> | ||
|  |           , mpl::if_< | ||
|  |                 is_convertible<Traversal,bidirectional_traversal_tag> | ||
|  |               , std::bidirectional_iterator_tag | ||
|  |               , std::forward_iterator_tag | ||
|  |             > | ||
|  |         > | ||
|  |       , typename mpl::eval_if< | ||
|  |             mpl::and_< | ||
|  |                 is_convertible<Traversal, single_pass_traversal_tag> | ||
|  | 
 | ||
|  |                 // check for readability | ||
|  |               , is_convertible<Reference, ValueParam> | ||
|  |             > | ||
|  |           , mpl::identity<std::input_iterator_tag> | ||
|  |           , mpl::identity<Traversal> | ||
|  |         > | ||
|  |     > | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | // True iff T is convertible to an old-style iterator category. | ||
|  | template <class T> | ||
|  | struct is_iterator_category | ||
|  |   : mpl::or_< | ||
|  |         is_convertible<T,std::input_iterator_tag> | ||
|  |       , is_convertible<T,std::output_iterator_tag> | ||
|  |     > | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | template <class T> | ||
|  | struct is_iterator_traversal | ||
|  |   : is_convertible<T,incrementable_traversal_tag> | ||
|  | {}; | ||
|  | 
 | ||
|  | // | ||
|  | // 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 <class Category, class Traversal> | ||
|  | struct iterator_category_with_traversal | ||
|  |   : Category, Traversal | ||
|  | { | ||
|  |     // 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_MPL_ASSERT_NOT(( | ||
|  |         is_convertible< | ||
|  |               typename iterator_category_to_traversal<Category>::type | ||
|  |             , Traversal | ||
|  |           >)); | ||
|  | 
 | ||
|  |     BOOST_MPL_ASSERT((is_iterator_category<Category>)); | ||
|  |     BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>)); | ||
|  |     BOOST_MPL_ASSERT_NOT((is_iterator_traversal<Category>)); | ||
|  | #  if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) | ||
|  |     BOOST_MPL_ASSERT((is_iterator_traversal<Traversal>)); | ||
|  | #  endif | ||
|  | }; | ||
|  | 
 | ||
|  | // Computes an iterator_category tag whose traversal is Traversal and | ||
|  | // which is appropriate for an iterator | ||
|  | template <class Traversal, class ValueParam, class Reference> | ||
|  | struct facade_iterator_category_impl | ||
|  | { | ||
|  |     BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>)); | ||
|  | 
 | ||
|  |     typedef typename iterator_facade_default_category< | ||
|  |         Traversal,ValueParam,Reference | ||
|  |     >::type category; | ||
|  | 
 | ||
|  |     typedef typename mpl::if_< | ||
|  |         is_same< | ||
|  |             Traversal | ||
|  |           , typename iterator_category_to_traversal<category>::type | ||
|  |         > | ||
|  |       , category | ||
|  |       , iterator_category_with_traversal<category,Traversal> | ||
|  |     >::type type; | ||
|  | }; | ||
|  | 
 | ||
|  | // | ||
|  | // Compute an iterator_category for iterator_facade | ||
|  | // | ||
|  | template <class CategoryOrTraversal, class ValueParam, class Reference> | ||
|  | struct facade_iterator_category | ||
|  |   : mpl::eval_if< | ||
|  |         is_iterator_category<CategoryOrTraversal> | ||
|  |       , mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is | ||
|  |       , facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference> | ||
|  |     > | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | }}} // namespace boost::iterators::detail | ||
|  | 
 | ||
|  | # include <boost/iterator/detail/config_undef.hpp> | ||
|  | 
 | ||
|  | #endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP |