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
advance_impl(InputIterator & it,Distance n,incrementable_traversal_tag)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
advance_impl(BidirectionalIterator & it,Distance n,bidirectional_traversal_tag)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
advance_impl(RandomAccessIterator & it,Distance n,random_access_traversal_tag)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
advance(InputIterator & it,Distance n)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 namespace iterators::advance_adl_barrier;
81 
82 } // namespace boost
83 
84 #endif
85