1 // (C) Copyright Jeremy Siek 2002. Permission to copy, use, modify,
2 // sell and distribute this software is granted provided this
3 // copyright notice appears in all copies. This software is provided
4 // "as is" without express or implied warranty, and with no claim as
5 // to its suitability for any purpose.
7 #ifndef BOOST_ITERATOR_CATEGORIES_HPP
8 # define BOOST_ITERATOR_CATEGORIES_HPP
10 # include <boost/config.hpp>
11 # include <boost/detail/iterator.hpp>
12 # include <boost/iterator/detail/config_def.hpp>
14 # include <boost/detail/workaround.hpp>
16 # include <boost/mpl/apply_if.hpp>
17 # include <boost/mpl/identity.hpp>
18 # include <boost/mpl/placeholders.hpp>
19 # include <boost/mpl/aux_/lambda_support.hpp>
21 # include <boost/type_traits/is_convertible.hpp>
23 # include <boost/static_assert.hpp>
28 // Traversal Categories
30 struct incrementable_traversal_tag {};
32 struct single_pass_traversal_tag
33 : incrementable_traversal_tag {};
35 struct forward_traversal_tag
36 : single_pass_traversal_tag {};
38 struct bidirectional_traversal_tag
39 : forward_traversal_tag {};
41 struct random_access_traversal_tag
42 : bidirectional_traversal_tag {};
47 // Convert a "strictly old-style" iterator category to a traversal
48 // tag. This is broken out into a separate metafunction to reduce
49 // the cost of instantiating iterator_category_to_traversal, below,
50 // for new-style types.
53 struct old_category_to_traversal
55 is_convertible<Cat,std::random_access_iterator_tag>
56 , mpl::identity<random_access_traversal_tag>
58 is_convertible<Cat,std::bidirectional_iterator_tag>
59 , mpl::identity<bidirectional_traversal_tag>
61 is_convertible<Cat,std::forward_iterator_tag>
62 , mpl::identity<forward_traversal_tag>
64 is_convertible<Cat,std::input_iterator_tag>
65 , mpl::identity<single_pass_traversal_tag>
67 is_convertible<Cat,std::output_iterator_tag>
68 , mpl::identity<incrementable_traversal_tag>
77 # if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
79 struct old_category_to_traversal<int>
85 template <class Traversal>
86 struct pure_traversal_tag
88 is_convertible<Traversal,random_access_traversal_tag>
89 , mpl::identity<random_access_traversal_tag>
91 is_convertible<Traversal,bidirectional_traversal_tag>
92 , mpl::identity<bidirectional_traversal_tag>
94 is_convertible<Traversal,forward_traversal_tag>
95 , mpl::identity<forward_traversal_tag>
97 is_convertible<Traversal,single_pass_traversal_tag>
98 , mpl::identity<single_pass_traversal_tag>
100 is_convertible<Traversal,incrementable_traversal_tag>
101 , mpl::identity<incrementable_traversal_tag>
111 # if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
113 struct pure_traversal_tag<int>
119 } // namespace detail
123 // Convert an iterator category into a traversal tag
126 struct iterator_category_to_traversal
127 : mpl::apply_if< // if already convertible to a traversal tag, we're done.
128 is_convertible<Cat,incrementable_traversal_tag>
130 , detail::old_category_to_traversal<Cat>
134 // Trait to get an iterator's traversal category
135 template <class Iterator = mpl::_1>
136 struct iterator_traversal
137 : iterator_category_to_traversal<
138 typename boost::detail::iterator_traits<Iterator>::iterator_category
142 # ifdef BOOST_MPL_NO_FULL_LAMBDA_SUPPORT
143 // Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
144 // out well. Instantiating the nested apply template also
145 // requires instantiating iterator_traits on the
146 // placeholder. Instead we just specialize it as a metafunction
149 struct iterator_traversal<mpl::_1>
152 struct apply : iterator_traversal<T>
156 struct iterator_traversal<mpl::_>
157 : iterator_traversal<mpl::_1>
163 #include <boost/iterator/detail/config_undef.hpp>
165 #endif // BOOST_ITERATOR_CATEGORIES_HPP