1/////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Ion Gaztanaga 2014-2014
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// See http://www.boost.org/libs/intrusive for documentation.
10//
11/////////////////////////////////////////////////////////////////////////////
12
13#ifndef BOOST_INTRUSIVE_DETAIL_ITERATOR_HPP
14#define BOOST_INTRUSIVE_DETAIL_ITERATOR_HPP
15
16#ifndef BOOST_CONFIG_HPP
17# include <boost/config.hpp>
18#endif
19
20#if defined(BOOST_HAS_PRAGMA_ONCE)
21# pragma once
22#endif
23
24#include <cstddef>
25#include <boost/intrusive/detail/std_fwd.hpp>
26#include <boost/intrusive/detail/workaround.hpp>
27#include <boost/move/detail/iterator_traits.hpp>
28#include <boost/move/detail/meta_utils_core.hpp>
29
30namespace boost{
31namespace iterators{
32
33struct incrementable_traversal_tag;
34struct single_pass_traversal_tag;
35struct forward_traversal_tag;
36struct bidirectional_traversal_tag;
37struct random_access_traversal_tag;
38
39namespace detail{
40
41template <class Category, class Traversal>
42struct iterator_category_with_traversal;
43
44} //namespace boost{
45} //namespace iterators{
46} //namespace detail{
47
48namespace boost {
49namespace intrusive {
50
51using boost::movelib::iterator_traits;
52
53////////////////////
54// iterator
55////////////////////
56template<class Category, class T, class Difference, class Pointer, class Reference>
57struct iterator
58{
59 typedef Category iterator_category;
60 typedef T value_type;
61 typedef Difference difference_type;
62 typedef Pointer pointer;
63 typedef Reference reference;
64};
65
66////////////////////////////////////////
67// iterator_[dis|en]able_if_boost_iterator
68////////////////////////////////////////
69template<class I>
70struct is_boost_iterator
71{
72 static const bool value = false;
73};
74
75template<class Category, class Traversal>
76struct is_boost_iterator< boost::iterators::detail::iterator_category_with_traversal<Category, Traversal> >
77{
78 static const bool value = true;
79};
80
81template<class I, class R = void>
82struct iterator_enable_if_boost_iterator
83 : ::boost::move_detail::enable_if_c
84 < is_boost_iterator<typename boost::intrusive::iterator_traits<I>::iterator_category >::value
85 , R>
86{};
87
88////////////////////////////////////////
89// iterator_[dis|en]able_if_tag
90////////////////////////////////////////
91template<class I, class Tag, class R = void>
92struct iterator_enable_if_tag
93 : ::boost::move_detail::enable_if_c
94 < ::boost::move_detail::is_same
95 < typename boost::intrusive::iterator_traits<I>::iterator_category
96 , Tag
97 >::value
98 , R>
99{};
100
101template<class I, class Tag, class R = void>
102struct iterator_disable_if_tag
103 : ::boost::move_detail::enable_if_c
104 < !::boost::move_detail::is_same
105 < typename boost::intrusive::iterator_traits<I>::iterator_category
106 , Tag
107 >::value
108 , R>
109{};
110
111////////////////////////////////////////
112// iterator_[dis|en]able_if_tag
113////////////////////////////////////////
114template<class I, class Tag, class Tag2, class R = void>
115struct iterator_enable_if_convertible_tag
116 : ::boost::move_detail::enable_if_c
117 < ::boost::move_detail::is_same_or_convertible
118 < typename boost::intrusive::iterator_traits<I>::iterator_category
119 , Tag
120 >::value &&
121 !::boost::move_detail::is_same_or_convertible
122 < typename boost::intrusive::iterator_traits<I>::iterator_category
123 , Tag2
124 >::value
125 , R>
126{};
127
128////////////////////////////////////////
129// iterator_[dis|en]able_if_tag_difference_type
130////////////////////////////////////////
131template<class I, class Tag>
132struct iterator_enable_if_tag_difference_type
133 : iterator_enable_if_tag<I, Tag, typename boost::intrusive::iterator_traits<I>::difference_type>
134{};
135
136template<class I, class Tag>
137struct iterator_disable_if_tag_difference_type
138 : iterator_disable_if_tag<I, Tag, typename boost::intrusive::iterator_traits<I>::difference_type>
139{};
140
141////////////////////
142// advance
143////////////////////
144
145template<class InputIt, class Distance>
146BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag<InputIt, std::input_iterator_tag>::type
147 iterator_advance(InputIt& it, Distance n)
148{
149 while(n--)
150 ++it;
151}
152
153template<class InputIt, class Distance>
154typename iterator_enable_if_tag<InputIt, std::forward_iterator_tag>::type
155 iterator_advance(InputIt& it, Distance n)
156{
157 while(n--)
158 ++it;
159}
160
161template<class InputIt, class Distance>
162BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag<InputIt, std::bidirectional_iterator_tag>::type
163 iterator_advance(InputIt& it, Distance n)
164{
165 for (; 0 < n; --n)
166 ++it;
167 for (; n < 0; ++n)
168 --it;
169}
170
171template<class InputIt, class Distance>
172BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag<InputIt, std::random_access_iterator_tag>::type
173 iterator_advance(InputIt& it, Distance n)
174{
175 it += n;
176}
177
178template<class InputIt, class Distance>
179BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
180 <InputIt, const boost::iterators::incrementable_traversal_tag&, const boost::iterators::single_pass_traversal_tag&>::type
181 iterator_advance(InputIt& it, Distance n)
182{
183 while(n--)
184 ++it;
185}
186
187template<class InputIt, class Distance>
188BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
189 <InputIt, const boost::iterators::single_pass_traversal_tag &, const boost::iterators::forward_traversal_tag&>::type
190 iterator_advance(InputIt& it, Distance n)
191{
192 while(n--)
193 ++it;
194}
195
196template<class InputIt, class Distance>
197BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
198 <InputIt, const boost::iterators::forward_traversal_tag&, const boost::iterators::bidirectional_traversal_tag&>::type
199 iterator_advance(InputIt& it, Distance n)
200{
201 while(n--)
202 ++it;
203}
204
205template<class InputIt, class Distance>
206BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
207 <InputIt, const boost::iterators::bidirectional_traversal_tag&, const boost::iterators::random_access_traversal_tag&>::type
208 iterator_advance(InputIt& it, Distance n)
209{
210 for (; 0 < n; --n)
211 ++it;
212 for (; n < 0; ++n)
213 --it;
214}
215
216class fake{};
217
218template<class InputIt, class Distance>
219BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_convertible_tag
220 <InputIt, const boost::iterators::random_access_traversal_tag&, const fake&>::type
221 iterator_advance(InputIt& it, Distance n)
222{
223 it += n;
224}
225
226////////////////////
227// distance
228////////////////////
229template<class InputIt> inline
230typename iterator_disable_if_tag_difference_type
231 <InputIt, std::random_access_iterator_tag>::type
232 iterator_distance(InputIt first, InputIt last)
233{
234 typename iterator_traits<InputIt>::difference_type off = 0;
235 while(first != last){
236 ++off;
237 ++first;
238 }
239 return off;
240}
241
242template<class InputIt>
243BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag_difference_type
244 <InputIt, std::random_access_iterator_tag>::type
245 iterator_distance(InputIt first, InputIt last)
246{
247 typename iterator_traits<InputIt>::difference_type off = last - first;
248 return off;
249}
250
251template<class I>
252BOOST_INTRUSIVE_FORCEINLINE typename iterator_traits<I>::pointer iterator_arrow_result(const I &i)
253{ return i.operator->(); }
254
255template<class T>
256BOOST_INTRUSIVE_FORCEINLINE T * iterator_arrow_result(T *p)
257{ return p; }
258
259} //namespace intrusive
260} //namespace boost
261
262#endif //BOOST_INTRUSIVE_DETAIL_ITERATOR_HPP
263