]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | // Copyright (C) 2019 T. Zachary Laine |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. (See | |
4 | // accompanying file LICENSE_1_0.txt or copy at | |
5 | // http://www.boost.org/LICENSE_1_0.txt) | |
6 | //[ interoperability | |
7 | #include <boost/stl_interfaces/iterator_interface.hpp> | |
8 | ||
9 | #include <algorithm> | |
10 | #include <array> | |
11 | #include <numeric> | |
12 | ||
13 | #include <cassert> | |
14 | ||
15 | ||
16 | // This is a random access iterator templated on a value type. The ValueType | |
17 | // template parameter allows us easily to define const and non-const iterators | |
18 | // from the same template. | |
19 | template<typename ValueType> | |
20 | struct random_access_iterator : boost::stl_interfaces::iterator_interface< | |
21 | random_access_iterator<ValueType>, | |
22 | std::random_access_iterator_tag, | |
23 | ValueType> | |
24 | { | |
25 | static_assert(std::is_object<ValueType>::value, ""); | |
26 | ||
27 | // Default constructor. | |
28 | constexpr random_access_iterator() noexcept {} | |
29 | ||
30 | // Construction from an underlying pointer. | |
31 | constexpr random_access_iterator(ValueType * it) noexcept : it_(it) {} | |
32 | ||
33 | // Implicit conversion from an existing random_access_iterator with a | |
34 | // possibly different value type. The enable_if logic here just enforces | |
35 | // that this constructor only participates in overload resolution when the | |
36 | // expression it_ = other.it_ is well-formed. | |
37 | template< | |
38 | typename ValueType2, | |
39 | typename E = std::enable_if_t< | |
40 | std::is_convertible<ValueType2 *, ValueType *>::value>> | |
41 | constexpr random_access_iterator( | |
42 | random_access_iterator<ValueType2> other) noexcept : | |
43 | it_(other.it_) | |
44 | {} | |
45 | ||
46 | constexpr ValueType & operator*() const noexcept { return *it_; } | |
47 | constexpr random_access_iterator & operator+=(std::ptrdiff_t i) noexcept | |
48 | { | |
49 | it_ += i; | |
50 | return *this; | |
51 | } | |
52 | constexpr auto operator-(random_access_iterator other) const noexcept | |
53 | { | |
54 | return it_ - other.it_; | |
55 | } | |
56 | ||
57 | private: | |
58 | ValueType * it_; | |
59 | ||
60 | // This friendship is necessary to enable the implicit conversion | |
61 | // constructor above to work. | |
62 | template<typename ValueType2> | |
63 | friend struct random_access_iterator; | |
64 | }; | |
65 | ||
66 | using iterator = random_access_iterator<int>; | |
67 | using const_iterator = random_access_iterator<int const>; | |
68 | ||
69 | int main() | |
70 | { | |
71 | std::array<int, 10> ints = {{0, 2, 1, 3, 4, 5, 7, 6, 8, 9}}; | |
72 | ||
73 | // Create and use two mutable iterators. | |
74 | iterator first(ints.data()); | |
75 | iterator last(ints.data() + ints.size()); | |
76 | std::sort(first, last); | |
77 | assert(ints == (std::array<int, 10>{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}})); | |
78 | ||
79 | // Create and use two constant iterators, one from an existing mutable | |
80 | // iterator. | |
81 | std::array<int, 10> int_sums; | |
82 | const_iterator cfirst(ints.data()); | |
83 | const_iterator clast = last; | |
84 | std::partial_sum(cfirst, clast, int_sums.begin()); | |
85 | assert(int_sums == (std::array<int, 10>{{0, 1, 3, 6, 10, 15, 21, 28, 36, 45}})); | |
86 | } | |
87 | //] |