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