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
29namespace boost {
30namespace intrusive {
31
32using boost::movelib::iterator_traits;
33
34////////////////////
35// iterator
36////////////////////
37template<class Category, class T, class Distance, class Pointer = T*, class Reference = T&>
38struct 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////////////////////////////////////////
50template<class I, class Tag, class R = void>
51struct 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
60template<class I, class Tag, class R = void>
61struct 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////////////////////////////////////////
73template<class I, class Tag>
74struct iterator_enable_if_tag_difference_type
75 : iterator_enable_if_tag<I, Tag, typename boost::intrusive::iterator_traits<I>::difference_type>
76{};
77
78template<class I, class Tag>
79struct 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////////////////////
86template<class InputIt, class Distance> inline
87typename 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
94template<class InputIt, class Distance> inline
95typename 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
102template<class InputIt, class Distance> inline
103typename 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
112template<class InputIt, class Distance> inline
113typename 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////////////////////
122template<class InputIt> inline
123typename 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
135template<class InputIt> inline
136typename 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