blob: 9adc13d042c3c1e1f1a9a8b3966339ece94d5d17 [file] [log] [blame]
Jeff Thompsona28eed82013-08-22 16:21:10 -07001// (C) Copyright Jeremy Siek 2002.
2// Distributed under the Boost Software License, Version 1.0. (See
3// accompanying file LICENSE_1_0.txt or copy at
4// http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef BOOST_ITERATOR_CATEGORIES_HPP
7# define BOOST_ITERATOR_CATEGORIES_HPP
8
9# include <ndnboost/config.hpp>
10# include <ndnboost/detail/iterator.hpp>
11# include <ndnboost/iterator/detail/config_def.hpp>
12
13# include <ndnboost/detail/workaround.hpp>
14
15# include <ndnboost/mpl/eval_if.hpp>
16# include <ndnboost/mpl/identity.hpp>
17# include <ndnboost/mpl/placeholders.hpp>
18# include <ndnboost/mpl/aux_/lambda_support.hpp>
19
20# include <ndnboost/type_traits/is_convertible.hpp>
21
22# include <ndnboost/static_assert.hpp>
23
24namespace ndnboost {
25
26//
27// Traversal Categories
28//
29
30struct no_traversal_tag {};
31
32struct incrementable_traversal_tag
33 : no_traversal_tag
34{
35// incrementable_traversal_tag() {}
36// incrementable_traversal_tag(std::output_iterator_tag const&) {};
37};
38
39struct single_pass_traversal_tag
40 : incrementable_traversal_tag
41{
42// single_pass_traversal_tag() {}
43// single_pass_traversal_tag(std::input_iterator_tag const&) {};
44};
45
46struct forward_traversal_tag
47 : single_pass_traversal_tag
48{
49// forward_traversal_tag() {}
50// forward_traversal_tag(std::forward_iterator_tag const&) {};
51};
52
53struct bidirectional_traversal_tag
54 : forward_traversal_tag
55{
56// bidirectional_traversal_tag() {};
57// bidirectional_traversal_tag(std::bidirectional_iterator_tag const&) {};
58};
59
60struct random_access_traversal_tag
61 : bidirectional_traversal_tag
62{
63// random_access_traversal_tag() {};
64// random_access_traversal_tag(std::random_access_iterator_tag const&) {};
65};
66
67namespace detail
68{
69 //
70 // Convert a "strictly old-style" iterator category to a traversal
71 // tag. This is broken out into a separate metafunction to reduce
72 // the cost of instantiating iterator_category_to_traversal, below,
73 // for new-style types.
74 //
75 template <class Cat>
76 struct old_category_to_traversal
77 : mpl::eval_if<
78 is_convertible<Cat,std::random_access_iterator_tag>
79 , mpl::identity<random_access_traversal_tag>
80 , mpl::eval_if<
81 is_convertible<Cat,std::bidirectional_iterator_tag>
82 , mpl::identity<bidirectional_traversal_tag>
83 , mpl::eval_if<
84 is_convertible<Cat,std::forward_iterator_tag>
85 , mpl::identity<forward_traversal_tag>
86 , mpl::eval_if<
87 is_convertible<Cat,std::input_iterator_tag>
88 , mpl::identity<single_pass_traversal_tag>
89 , mpl::eval_if<
90 is_convertible<Cat,std::output_iterator_tag>
91 , mpl::identity<incrementable_traversal_tag>
92 , void
93 >
94 >
95 >
96 >
97 >
98 {};
99
100# if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
101 template <>
102 struct old_category_to_traversal<int>
103 {
104 typedef int type;
105 };
106# endif
107
108 template <class Traversal>
109 struct pure_traversal_tag
110 : mpl::eval_if<
111 is_convertible<Traversal,random_access_traversal_tag>
112 , mpl::identity<random_access_traversal_tag>
113 , mpl::eval_if<
114 is_convertible<Traversal,bidirectional_traversal_tag>
115 , mpl::identity<bidirectional_traversal_tag>
116 , mpl::eval_if<
117 is_convertible<Traversal,forward_traversal_tag>
118 , mpl::identity<forward_traversal_tag>
119 , mpl::eval_if<
120 is_convertible<Traversal,single_pass_traversal_tag>
121 , mpl::identity<single_pass_traversal_tag>
122 , mpl::eval_if<
123 is_convertible<Traversal,incrementable_traversal_tag>
124 , mpl::identity<incrementable_traversal_tag>
125 , void
126 >
127 >
128 >
129 >
130 >
131 {
132 };
133
134# if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
135 template <>
136 struct pure_traversal_tag<int>
137 {
138 typedef int type;
139 };
140# endif
141
142} // namespace detail
143
144
145//
146// Convert an iterator category into a traversal tag
147//
148template <class Cat>
149struct iterator_category_to_traversal
150 : mpl::eval_if< // if already convertible to a traversal tag, we're done.
151 is_convertible<Cat,incrementable_traversal_tag>
152 , mpl::identity<Cat>
153 , ndnboost::detail::old_category_to_traversal<Cat>
154 >
155{};
156
157// Trait to get an iterator's traversal category
158template <class Iterator = mpl::_1>
159struct iterator_traversal
160 : iterator_category_to_traversal<
161 typename ndnboost::detail::iterator_traits<Iterator>::iterator_category
162 >
163{};
164
165# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
166// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
167// out well. Instantiating the nested apply template also
168// requires instantiating iterator_traits on the
169// placeholder. Instead we just specialize it as a metafunction
170// class.
171template <>
172struct iterator_traversal<mpl::_1>
173{
174 template <class T>
175 struct apply : iterator_traversal<T>
176 {};
177};
178template <>
179struct iterator_traversal<mpl::_>
180 : iterator_traversal<mpl::_1>
181{};
182# endif
183
184} // namespace ndnboost
185
186#include <ndnboost/iterator/detail/config_undef.hpp>
187
188#endif // BOOST_ITERATOR_CATEGORIES_HPP