]> git.lyx.org Git - lyx.git/blob - boost/boost/iterator/iterator_categories.hpp
Boost 1.31.0
[lyx.git] / boost / boost / iterator / iterator_categories.hpp
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.
6
7 #ifndef BOOST_ITERATOR_CATEGORIES_HPP
8 # define BOOST_ITERATOR_CATEGORIES_HPP
9
10 # include <boost/config.hpp>
11 # include <boost/detail/iterator.hpp>
12 # include <boost/iterator/detail/config_def.hpp>
13
14 # include <boost/detail/workaround.hpp>
15
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>
20
21 # include <boost/type_traits/is_convertible.hpp>
22
23 # include <boost/static_assert.hpp>
24
25 namespace boost {
26
27 //
28 // Traversal Categories
29 //
30 struct incrementable_traversal_tag {};
31   
32 struct single_pass_traversal_tag
33   : incrementable_traversal_tag {};
34   
35 struct forward_traversal_tag
36   : single_pass_traversal_tag {};
37   
38 struct bidirectional_traversal_tag
39   : forward_traversal_tag {};
40   
41 struct random_access_traversal_tag
42   : bidirectional_traversal_tag {};
43
44 namespace detail
45 {  
46   //
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.
51   //
52   template <class Cat>
53   struct old_category_to_traversal
54     : mpl::apply_if<
55           is_convertible<Cat,std::random_access_iterator_tag>
56         , mpl::identity<random_access_traversal_tag>
57         , mpl::apply_if<
58               is_convertible<Cat,std::bidirectional_iterator_tag>
59             , mpl::identity<bidirectional_traversal_tag>
60             , mpl::apply_if<
61                   is_convertible<Cat,std::forward_iterator_tag>
62                 , mpl::identity<forward_traversal_tag>
63                 , mpl::apply_if<
64                       is_convertible<Cat,std::input_iterator_tag>
65                     , mpl::identity<single_pass_traversal_tag>
66                     , mpl::apply_if<
67                           is_convertible<Cat,std::output_iterator_tag>
68                         , mpl::identity<incrementable_traversal_tag>
69                         , void
70                       >
71                   >
72               >
73           >
74       >
75   {};
76
77 # if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
78   template <>
79   struct old_category_to_traversal<int>
80   {
81       typedef int type;
82   };
83 # endif
84
85   template <class Traversal>
86   struct pure_traversal_tag
87     : mpl::apply_if<
88           is_convertible<Traversal,random_access_traversal_tag>
89         , mpl::identity<random_access_traversal_tag>
90         , mpl::apply_if<
91               is_convertible<Traversal,bidirectional_traversal_tag>
92             , mpl::identity<bidirectional_traversal_tag>
93             , mpl::apply_if<
94                   is_convertible<Traversal,forward_traversal_tag>
95                 , mpl::identity<forward_traversal_tag>
96                 , mpl::apply_if<
97                       is_convertible<Traversal,single_pass_traversal_tag>
98                     , mpl::identity<single_pass_traversal_tag>
99                     , mpl::apply_if<
100                           is_convertible<Traversal,incrementable_traversal_tag>
101                         , mpl::identity<incrementable_traversal_tag>
102                         , void
103                       >
104                   >
105               >
106           >
107       >
108   {
109   };
110   
111 # if BOOST_WORKAROUND(BOOST_MSVC, == 1200)
112   template <>
113   struct pure_traversal_tag<int>
114   {
115       typedef int type;
116   };
117 # endif
118
119 } // namespace detail
120
121
122 //
123 // Convert an iterator category into a traversal tag
124 //
125 template <class Cat>
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>
129       , mpl::identity<Cat>
130       , detail::old_category_to_traversal<Cat>
131     >
132 {};
133
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
139     >
140 {};
141
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
147 // class.
148 template <>
149 struct iterator_traversal<mpl::_1>
150 {
151     template <class T>
152     struct apply : iterator_traversal<T>
153     {};
154 };
155 template <>
156 struct iterator_traversal<mpl::_>
157   : iterator_traversal<mpl::_1>
158 {};
159 # endif
160
161 } // namespace boost
162
163 #include <boost/iterator/detail/config_undef.hpp>
164
165 #endif // BOOST_ITERATOR_CATEGORIES_HPP