1 | // Copyright (C) 2017 Michel Morin. |
2 | // |
3 | // Distributed under the Boost Software License, Version 1.0. |
4 | // (See accompanying file LICENSE_1_0.txt or copy at |
5 | // http://www.boost.org/LICENSE_1_0.txt) |
6 | |
7 | #ifndef BOOST_ITERATOR_ADVANCE_HPP |
8 | #define BOOST_ITERATOR_ADVANCE_HPP |
9 | |
10 | #include <boost/config.hpp> |
11 | #include <boost/iterator/iterator_categories.hpp> |
12 | |
13 | namespace boost { |
14 | namespace iterators { |
15 | |
16 | namespace detail { |
17 | template <typename InputIterator, typename Distance> |
18 | inline BOOST_CXX14_CONSTEXPR void |
19 | advance_impl( |
20 | InputIterator& it |
21 | , Distance n |
22 | , incrementable_traversal_tag |
23 | ) |
24 | { |
25 | while (n > 0) { |
26 | ++it; |
27 | --n; |
28 | } |
29 | } |
30 | |
31 | template <typename BidirectionalIterator, typename Distance> |
32 | inline BOOST_CXX14_CONSTEXPR void |
33 | advance_impl( |
34 | BidirectionalIterator& it |
35 | , Distance n |
36 | , bidirectional_traversal_tag |
37 | ) |
38 | { |
39 | if (n >= 0) { |
40 | while (n > 0) { |
41 | ++it; |
42 | --n; |
43 | } |
44 | } |
45 | else { |
46 | while (n < 0) { |
47 | --it; |
48 | ++n; |
49 | } |
50 | } |
51 | } |
52 | |
53 | template <typename RandomAccessIterator, typename Distance> |
54 | inline BOOST_CXX14_CONSTEXPR void |
55 | advance_impl( |
56 | RandomAccessIterator& it |
57 | , Distance n |
58 | , random_access_traversal_tag |
59 | ) |
60 | { |
61 | it += n; |
62 | } |
63 | } |
64 | |
65 | namespace advance_adl_barrier { |
66 | template <typename InputIterator, typename Distance> |
67 | inline BOOST_CXX14_CONSTEXPR void |
68 | advance(InputIterator& it, Distance n) |
69 | { |
70 | detail::advance_impl( |
71 | it, n, typename iterator_traversal<InputIterator>::type() |
72 | ); |
73 | } |
74 | } |
75 | |
76 | using namespace advance_adl_barrier; |
77 | |
78 | } // namespace iterators |
79 | |
80 | using iterators::advance; |
81 | |
82 | } // namespace boost |
83 | |
84 | #endif |
85 | |