]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/stl_interfaces/example/zip_proxy_iterator.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / stl_interfaces / example / zip_proxy_iterator.cpp
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 //[ zip_proxy_iterator
7 #include <boost/stl_interfaces/iterator_interface.hpp>
8
9 #include <algorithm>
10 #include <array>
11 #include <tuple>
12
13 #include <cassert>
14
15
16 // This is a zip iterator, meaning that it iterates over a notional sequence
17 // of pairs that is formed from two actual sequences of scalars. To make this
18 // iterator writable, it needs to have a reference type that is not actually a
19 // reference -- the reference type is a pair of references, std::tuple<int &,
20 // int &>.
21 struct zip_iterator : boost::stl_interfaces::proxy_iterator_interface<
22 zip_iterator,
23 std::random_access_iterator_tag,
24 std::tuple<int, int>,
25 std::tuple<int &, int &>>
26 {
27 constexpr zip_iterator() noexcept : it1_(), it2_() {}
28 constexpr zip_iterator(int * it1, int * it2) noexcept : it1_(it1), it2_(it2)
29 {}
30
31 constexpr std::tuple<int &, int &> operator*() const noexcept
32 {
33 return std::tuple<int &, int &>{*it1_, *it2_};
34 }
35 constexpr zip_iterator & operator += (std::ptrdiff_t i) noexcept
36 {
37 it1_ += i;
38 it2_ += i;
39 return *this;
40 }
41 constexpr auto operator-(zip_iterator other) const noexcept
42 {
43 return it1_ - other.it1_;
44 }
45
46 private:
47 int * it1_;
48 int * it2_;
49 };
50
51
52 namespace std {
53 // Required for std::sort to work with zip_iterator. Without this
54 // overload, std::sort eventually tries to call std::swap(*it1, *it2),
55 // *it1 and *it2 are rvalues, and std::swap() takes mutable lvalue
56 // references. That makes std::swap(*it1, *it2) ill-formed.
57 //
58 // Note that this overload does not conflict with any other swap()
59 // overloads, since this one takes rvalue reference parameters.
60 //
61 // Also note that this overload has to be in namespace std only because
62 // ADL cannot find it anywhere else. If
63 // zip_iterator::reference/std::tuple's template parameters were not
64 // builtins, this overload could be in whatever namespace those template
65 // parameters were declared in.
66 void swap(zip_iterator::reference && lhs, zip_iterator::reference && rhs)
67 {
68 using std::swap;
69 swap(std::get<0>(lhs), std::get<0>(rhs));
70 swap(std::get<1>(lhs), std::get<1>(rhs));
71 }
72 }
73
74
75 int main()
76 {
77 std::array<int, 10> ints = {{2, 0, 1, 5, 3, 6, 8, 4, 9, 7}};
78 std::array<int, 10> ones = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
79
80 {
81 std::array<std::tuple<int, int>, 10> const result = {{
82 {2, 1},
83 {0, 1},
84 {1, 1},
85 {5, 1},
86 {3, 1},
87 {6, 1},
88 {8, 1},
89 {4, 1},
90 {9, 1},
91 {7, 1},
92 }};
93
94 zip_iterator first(ints.data(), ones.data());
95 zip_iterator last(ints.data() + ints.size(), ones.data() + ones.size());
96 assert(std::equal(first, last, result.begin(), result.end()));
97 }
98
99 {
100 std::array<std::tuple<int, int>, 10> const result = {{
101 {0, 1},
102 {1, 1},
103 {2, 1},
104 {3, 1},
105 {4, 1},
106 {5, 1},
107 {6, 1},
108 {7, 1},
109 {8, 1},
110 {9, 1},
111 }};
112 zip_iterator first(ints.data(), ones.data());
113 zip_iterator last(ints.data() + ints.size(), ones.data() + ones.size());
114 assert(!std::equal(first, last, result.begin(), result.end()));
115 std::sort(first, last);
116 assert(std::equal(first, last, result.begin(), result.end()));
117 }
118 }
119 //]