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
30 namespace boost {
31 namespace intrusive {
32
33 using boost::movelib::iterator_traits;
34
35 ////////////////////
36 // iterator
37 ////////////////////
38 template<class Category, class T, class Difference, class Pointer, class Reference>
39 struct iterator
40 {
41 typedef Category iterator_category;
42 typedef T value_type;
43 typedef Difference difference_type;
44 typedef Pointer pointer;
45 typedef Reference reference;
46 };
47
48 ////////////////////////////////////////
49 // iterator_[dis|en]able_if_tag
50 ////////////////////////////////////////
51 template<class I, class Tag, class R = void>
52 struct iterator_enable_if_tag
53 : ::boost::move_detail::enable_if_c
54 < ::boost::move_detail::is_same
55 < typename boost::intrusive::iterator_traits<I>::iterator_category
56 , Tag
57 >::value
58 , R>
59 {};
60
61 template<class I, class Tag, class R = void>
62 struct iterator_disable_if_tag
63 : ::boost::move_detail::enable_if_c
64 < !::boost::move_detail::is_same
65 < typename boost::intrusive::iterator_traits<I>::iterator_category
66 , Tag
67 >::value
68 , R>
69 {};
70
71 ////////////////////////////////////////
72 // iterator_[dis|en]able_if_tag_difference_type
73 ////////////////////////////////////////
74 template<class I, class Tag>
75 struct iterator_enable_if_tag_difference_type
76 : iterator_enable_if_tag<I, Tag, typename boost::intrusive::iterator_traits<I>::difference_type>
77 {};
78
79 template<class I, class Tag>
80 struct iterator_disable_if_tag_difference_type
81 : iterator_disable_if_tag<I, Tag, typename boost::intrusive::iterator_traits<I>::difference_type>
82 {};
83
84 ////////////////////
85 // advance
86 ////////////////////
87 template<class InputIt, class Distance>
88 typename iterator_enable_if_tag<InputIt, std::input_iterator_tag>::type
iterator_advance(InputIt & it,Distance n)89 iterator_advance(InputIt& it, Distance n)
90 {
91 while(n--)
92 ++it;
93 }
94
95 template<class InputIt, class Distance>
96 typename iterator_enable_if_tag<InputIt, std::forward_iterator_tag>::type
iterator_advance(InputIt & it,Distance n)97 iterator_advance(InputIt& it, Distance n)
98 {
99 while(n--)
100 ++it;
101 }
102
103 template<class InputIt, class Distance>
104 typename iterator_enable_if_tag<InputIt, std::bidirectional_iterator_tag>::type
iterator_advance(InputIt & it,Distance n)105 iterator_advance(InputIt& it, Distance n)
106 {
107 for (; 0 < n; --n)
108 ++it;
109 for (; n < 0; ++n)
110 --it;
111 }
112
113 template<class InputIt, class Distance>
114 BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag<InputIt, std::random_access_iterator_tag>::type
iterator_advance(InputIt & it,Distance n)115 iterator_advance(InputIt& it, Distance n)
116 {
117 it += n;
118 }
119
120 ////////////////////
121 // distance
122 ////////////////////
123 template<class InputIt> inline
124 typename iterator_disable_if_tag_difference_type
125 <InputIt, std::random_access_iterator_tag>::type
iterator_distance(InputIt first,InputIt last)126 iterator_distance(InputIt first, InputIt last)
127 {
128 typename iterator_traits<InputIt>::difference_type off = 0;
129 while(first != last){
130 ++off;
131 ++first;
132 }
133 return off;
134 }
135
136 template<class InputIt>
137 BOOST_INTRUSIVE_FORCEINLINE typename iterator_enable_if_tag_difference_type
138 <InputIt, std::random_access_iterator_tag>::type
iterator_distance(InputIt first,InputIt last)139 iterator_distance(InputIt first, InputIt last)
140 {
141 typename iterator_traits<InputIt>::difference_type off = last - first;
142 return off;
143 }
144
145 template<class I>
iterator_arrow_result(const I & i)146 BOOST_INTRUSIVE_FORCEINLINE typename iterator_traits<I>::pointer iterator_arrow_result(const I &i)
147 { return i.operator->(); }
148
149 template<class T>
iterator_arrow_result(T * p)150 BOOST_INTRUSIVE_FORCEINLINE T * iterator_arrow_result(T *p)
151 { return p; }
152
153 } //namespace intrusive
154 } //namespace boost
155
156 #endif //BOOST_INTRUSIVE_DETAIL_ITERATOR_HPP
157