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
iterator_advance(InputIt & it,Distance n)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
iterator_advance(InputIt & it,Distance n)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
iterator_advance(InputIt & it,Distance n)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
iterator_advance(InputIt & it,Distance n)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
iterator_distance(InputIt first,InputIt last)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
iterator_distance(InputIt first,InputIt last)138       iterator_distance(InputIt first, InputIt last)
139 {
140    typename iterator_traits<InputIt>::difference_type off = last - first;
141    return off;
142 }
143 
144 template<class I>
iterator_arrow_result(const I & i)145 typename iterator_traits<I>::pointer iterator_arrow_result(const I &i)
146 {  return i.operator->();  }
147 
148 template<class T>
iterator_arrow_result(T * p)149 T * iterator_arrow_result(T *p)
150 {  return p;   }
151 
152 } //namespace intrusive
153 } //namespace boost
154 
155 #endif //BOOST_INTRUSIVE_DETAIL_ITERATOR_HPP
156