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