12c3bbac0SNikolas Klauser //===----------------------------------------------------------------------===//
22c3bbac0SNikolas Klauser //
32c3bbac0SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42c3bbac0SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
52c3bbac0SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62c3bbac0SNikolas Klauser //
72c3bbac0SNikolas Klauser //===----------------------------------------------------------------------===//
82c3bbac0SNikolas Klauser
92c3bbac0SNikolas Klauser // UNSUPPORTED: c++03, c++11, c++14, c++17
10520c7fbbSLouis Dionne // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
11520c7fbbSLouis Dionne
12520c7fbbSLouis Dionne // <algorithm>
132c3bbac0SNikolas Klauser
142c3bbac0SNikolas Klauser // template<bidirectional_iterator I1, sentinel_for<I1> S1, bidirectional_iterator I2>
152c3bbac0SNikolas Klauser // requires indirectly_movable<I1, I2>
162c3bbac0SNikolas Klauser // constexpr ranges::move_backward_result<I1, I2>
172c3bbac0SNikolas Klauser // ranges::move_backward(I1 first, S1 last, I2 result);
182c3bbac0SNikolas Klauser // template<bidirectional_range R, bidirectional_iterator I>
192c3bbac0SNikolas Klauser // requires indirectly_movable<iterator_t<R>, I>
202c3bbac0SNikolas Klauser // constexpr ranges::move_backward_result<borrowed_iterator_t<R>, I>
212c3bbac0SNikolas Klauser // ranges::move_backward(R&& r, I result);
222c3bbac0SNikolas Klauser
232c3bbac0SNikolas Klauser #include <algorithm>
242c3bbac0SNikolas Klauser #include <array>
252c3bbac0SNikolas Klauser #include <cassert>
26c9080145SNikolas Klauser #include <deque>
276f36ead5SLouis Dionne #include <iterator>
282c3bbac0SNikolas Klauser #include <ranges>
29c9080145SNikolas Klauser #include <vector>
302c3bbac0SNikolas Klauser
312c3bbac0SNikolas Klauser #include "almost_satisfies_types.h"
322c3bbac0SNikolas Klauser #include "MoveOnly.h"
332c3bbac0SNikolas Klauser #include "test_iterators.h"
342c3bbac0SNikolas Klauser
352c3bbac0SNikolas Klauser template <class In, class Out = In, class Sent = sentinel_wrapper<In>>
362c3bbac0SNikolas Klauser concept HasMoveBackwardIt = requires(In in, Sent sent, Out out) { std::ranges::move_backward(in, sent, out); };
372c3bbac0SNikolas Klauser
382c3bbac0SNikolas Klauser static_assert(HasMoveBackwardIt<int*>);
392c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardIt<InputIteratorNotDerivedFrom>);
402c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardIt<InputIteratorNotIndirectlyReadable>);
412c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardIt<InputIteratorNotInputOrOutputIterator>);
422c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardIt<int*, WeaklyIncrementableNotMovable>);
432c3bbac0SNikolas Klauser struct NotIndirectlyCopyable {};
442c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardIt<int*, NotIndirectlyCopyable*>);
452c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardIt<int*, int*, SentinelForNotSemiregular>);
462c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardIt<int*, int*, SentinelForNotWeaklyEqualityComparableWith>);
472c3bbac0SNikolas Klauser
482c3bbac0SNikolas Klauser template <class Range, class Out>
492c3bbac0SNikolas Klauser concept HasMoveBackwardR = requires(Range range, Out out) { std::ranges::move_backward(range, out); };
502c3bbac0SNikolas Klauser
512c3bbac0SNikolas Klauser static_assert(HasMoveBackwardR<std::array<int, 10>, int*>);
522c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardR<InputRangeNotDerivedFrom, int*>);
532c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardR<InputRangeNotIndirectlyReadable, int*>);
542c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardR<InputRangeNotInputOrOutputIterator, int*>);
552c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardR<WeaklyIncrementableNotMovable, int*>);
562c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardR<UncheckedRange<NotIndirectlyCopyable*>, int*>);
572c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardR<InputRangeNotSentinelSemiregular, int*>);
582c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardR<InputRangeNotSentinelEqualityComparableWith, int*>);
592c3bbac0SNikolas Klauser static_assert(!HasMoveBackwardR<UncheckedRange<int*>, WeaklyIncrementableNotMovable>);
602c3bbac0SNikolas Klauser
612c3bbac0SNikolas Klauser static_assert(std::is_same_v<std::ranges::copy_result<int, long>, std::ranges::in_out_result<int, long>>);
622c3bbac0SNikolas Klauser
632c3bbac0SNikolas Klauser template <class In, class Out, class Sent, int N>
test(std::array<int,N> in)642c3bbac0SNikolas Klauser constexpr void test(std::array<int, N> in) {
652c3bbac0SNikolas Klauser {
662c3bbac0SNikolas Klauser std::array<int, N> out;
672c3bbac0SNikolas Klauser std::same_as<std::ranges::in_out_result<In, Out>> decltype(auto) ret =
682c3bbac0SNikolas Klauser std::ranges::move_backward(In(in.data()), Sent(In(in.data() + in.size())), Out(out.data() + out.size()));
692c3bbac0SNikolas Klauser assert(in == out);
70f537a01dSKonstantin Varlamov assert(base(ret.in) == in.data() + in.size());
712c3bbac0SNikolas Klauser assert(base(ret.out) == out.data());
722c3bbac0SNikolas Klauser }
732c3bbac0SNikolas Klauser {
742c3bbac0SNikolas Klauser std::array<int, N> out;
752c3bbac0SNikolas Klauser auto range = std::ranges::subrange(In(in.data()), Sent(In(in.data() + in.size())));
762c3bbac0SNikolas Klauser std::same_as<std::ranges::in_out_result<In, Out>> decltype(auto) ret =
772c3bbac0SNikolas Klauser std::ranges::move_backward(range, Out(out.data() + out.size()));
782c3bbac0SNikolas Klauser assert(in == out);
79f537a01dSKonstantin Varlamov assert(base(ret.in) == in.data() + in.size());
802c3bbac0SNikolas Klauser assert(base(ret.out) == out.data());
812c3bbac0SNikolas Klauser }
822c3bbac0SNikolas Klauser }
832c3bbac0SNikolas Klauser
842c3bbac0SNikolas Klauser template <class In, class Out, class Sent = In>
test_iterators()852c3bbac0SNikolas Klauser constexpr void test_iterators() {
862c3bbac0SNikolas Klauser // simple test
872c3bbac0SNikolas Klauser test<In, Out, Sent, 4>({1, 2, 3, 4});
882c3bbac0SNikolas Klauser // check that an empty range works
892c3bbac0SNikolas Klauser test<In, Out, Sent, 0>({});
902c3bbac0SNikolas Klauser }
912c3bbac0SNikolas Klauser
92c9080145SNikolas Klauser template <class InContainer, class OutContainer, class In, class Out, class Sent = In>
test_containers()93c9080145SNikolas Klauser constexpr void test_containers() {
94c9080145SNikolas Klauser {
95c9080145SNikolas Klauser InContainer in {1, 2, 3, 4};
96c9080145SNikolas Klauser OutContainer out(4);
97c9080145SNikolas Klauser std::same_as<std::ranges::in_out_result<In, Out>> auto ret =
98c9080145SNikolas Klauser std::ranges::move_backward(In(in.begin()), Sent(In(in.end())), Out(out.end()));
99c9080145SNikolas Klauser assert(std::ranges::equal(in, out));
100c9080145SNikolas Klauser assert(base(ret.in) == in.end());
101c9080145SNikolas Klauser assert(base(ret.out) == out.begin());
102c9080145SNikolas Klauser }
103c9080145SNikolas Klauser {
104c9080145SNikolas Klauser InContainer in {1, 2, 3, 4};
105c9080145SNikolas Klauser OutContainer out(4);
106c9080145SNikolas Klauser auto range = std::ranges::subrange(In(in.begin()), Sent(In(in.end())));
107c9080145SNikolas Klauser std::same_as<std::ranges::in_out_result<In, Out>> auto ret = std::ranges::move_backward(range, Out(out.end()));
108c9080145SNikolas Klauser assert(std::ranges::equal(in, out));
109c9080145SNikolas Klauser assert(base(ret.in) == in.end());
110c9080145SNikolas Klauser assert(base(ret.out) == out.begin());
111c9080145SNikolas Klauser }
112c9080145SNikolas Klauser }
113c9080145SNikolas Klauser
114c9080145SNikolas Klauser template <template <class> class InIter, template <class> class OutIter>
test_sentinels()1155629d492Svarconst constexpr void test_sentinels() {
116c9080145SNikolas Klauser test_iterators<InIter<int*>, OutIter<int*>, InIter<int*>>();
117c9080145SNikolas Klauser test_iterators<InIter<int*>, OutIter<int*>, sentinel_wrapper<InIter<int*>>>();
118c9080145SNikolas Klauser test_iterators<InIter<int*>, OutIter<int*>, sized_sentinel<InIter<int*>>>();
119c9080145SNikolas Klauser
120c9080145SNikolas Klauser if (!std::is_constant_evaluated()) {
121c9080145SNikolas Klauser if constexpr (!std::is_same_v<InIter<int*>, contiguous_iterator<int*>> &&
122c9080145SNikolas Klauser !std::is_same_v<OutIter<int*>, contiguous_iterator<int*>> &&
123c9080145SNikolas Klauser !std::is_same_v<InIter<int*>, ContiguousProxyIterator<int*>> &&
124c9080145SNikolas Klauser !std::is_same_v<OutIter<int*>, ContiguousProxyIterator<int*>>) {
125c9080145SNikolas Klauser test_containers<std::deque<int>,
126c9080145SNikolas Klauser std::deque<int>,
127c9080145SNikolas Klauser InIter<std::deque<int>::iterator>,
128c9080145SNikolas Klauser OutIter<std::deque<int>::iterator>>();
129c9080145SNikolas Klauser test_containers<std::deque<int>,
130c9080145SNikolas Klauser std::vector<int>,
131c9080145SNikolas Klauser InIter<std::deque<int>::iterator>,
132c9080145SNikolas Klauser OutIter<std::vector<int>::iterator>>();
133c9080145SNikolas Klauser test_containers<std::vector<int>,
134c9080145SNikolas Klauser std::deque<int>,
135c9080145SNikolas Klauser InIter<std::vector<int>::iterator>,
136c9080145SNikolas Klauser OutIter<std::deque<int>::iterator>>();
137c9080145SNikolas Klauser test_containers<std::vector<int>,
138c9080145SNikolas Klauser std::vector<int>,
139c9080145SNikolas Klauser InIter<std::vector<int>::iterator>,
140c9080145SNikolas Klauser OutIter<std::vector<int>::iterator>>();
141c9080145SNikolas Klauser }
142c9080145SNikolas Klauser }
1435629d492Svarconst }
1445629d492Svarconst
145c9080145SNikolas Klauser template <template <class> class Out>
test_in_iterators()1462c3bbac0SNikolas Klauser constexpr void test_in_iterators() {
147c9080145SNikolas Klauser test_sentinels<bidirectional_iterator, Out>();
148c9080145SNikolas Klauser test_sentinels<random_access_iterator, Out>();
149c9080145SNikolas Klauser test_sentinels<contiguous_iterator, Out>();
150c9080145SNikolas Klauser test_sentinels<std::type_identity_t, Out>();
1512c3bbac0SNikolas Klauser }
1522c3bbac0SNikolas Klauser
153c9080145SNikolas Klauser template <template <class> class Out>
test_proxy_in_iterators()154a81cc1fcSHui Xie constexpr void test_proxy_in_iterators() {
155c9080145SNikolas Klauser test_sentinels<BidirectionalProxyIterator, Out>();
156c9080145SNikolas Klauser test_sentinels<RandomAccessProxyIterator, Out>();
157c9080145SNikolas Klauser test_sentinels<ContiguousProxyIterator, Out>();
158c9080145SNikolas Klauser test_sentinels<ProxyIterator, Out>();
159a81cc1fcSHui Xie }
160a81cc1fcSHui Xie
1612c3bbac0SNikolas Klauser struct IteratorWithMoveIter {
1622c3bbac0SNikolas Klauser using value_type = int;
1632c3bbac0SNikolas Klauser using difference_type = int;
1642c3bbac0SNikolas Klauser explicit IteratorWithMoveIter() = default;
1652c3bbac0SNikolas Klauser int* ptr;
IteratorWithMoveIterIteratorWithMoveIter1662c3bbac0SNikolas Klauser constexpr IteratorWithMoveIter(int* ptr_) : ptr(ptr_) {}
1672c3bbac0SNikolas Klauser
1682c3bbac0SNikolas Klauser constexpr int& operator*() const; // iterator with iter_move should not be dereferenced
1692c3bbac0SNikolas Klauser
operator ++IteratorWithMoveIter1702c3bbac0SNikolas Klauser constexpr IteratorWithMoveIter& operator++() { ++ptr; return *this; }
operator ++IteratorWithMoveIter1712c3bbac0SNikolas Klauser constexpr IteratorWithMoveIter operator++(int) { auto ret = *this; ++*this; return ret; }
1722c3bbac0SNikolas Klauser
operator --IteratorWithMoveIter1732c3bbac0SNikolas Klauser constexpr IteratorWithMoveIter& operator--() { --ptr; return *this; }
operator --IteratorWithMoveIter1742c3bbac0SNikolas Klauser constexpr IteratorWithMoveIter operator--(int) { auto ret = *this; --*this; return ret; }
1752c3bbac0SNikolas Klauser
iter_move(const IteratorWithMoveIter &)1762c3bbac0SNikolas Klauser friend constexpr int iter_move(const IteratorWithMoveIter&) { return 42; }
1772c3bbac0SNikolas Klauser
1782c3bbac0SNikolas Klauser constexpr bool operator==(const IteratorWithMoveIter& other) const = default;
1792c3bbac0SNikolas Klauser };
1802c3bbac0SNikolas Klauser
test()1812c3bbac0SNikolas Klauser constexpr bool test() {
182c9080145SNikolas Klauser test_in_iterators<bidirectional_iterator>();
183c9080145SNikolas Klauser test_in_iterators<random_access_iterator>();
184c9080145SNikolas Klauser test_in_iterators<contiguous_iterator>();
185c9080145SNikolas Klauser test_in_iterators<std::type_identity_t>();
1862c3bbac0SNikolas Klauser
187c9080145SNikolas Klauser test_proxy_in_iterators<BidirectionalProxyIterator>();
188c9080145SNikolas Klauser test_proxy_in_iterators<RandomAccessProxyIterator>();
189c9080145SNikolas Klauser test_proxy_in_iterators<ContiguousProxyIterator>();
190c9080145SNikolas Klauser test_proxy_in_iterators<ProxyIterator>();
191a81cc1fcSHui Xie
1922c3bbac0SNikolas Klauser { // check that a move-only type works
1936f36ead5SLouis Dionne // When non-trivial
1942c3bbac0SNikolas Klauser {
1952c3bbac0SNikolas Klauser MoveOnly a[] = {1, 2, 3};
1962c3bbac0SNikolas Klauser MoveOnly b[3];
1972c3bbac0SNikolas Klauser std::ranges::move_backward(a, std::end(b));
1982c3bbac0SNikolas Klauser assert(b[0].get() == 1);
1992c3bbac0SNikolas Klauser assert(b[1].get() == 2);
2002c3bbac0SNikolas Klauser assert(b[2].get() == 3);
2012c3bbac0SNikolas Klauser }
2022c3bbac0SNikolas Klauser {
2032c3bbac0SNikolas Klauser MoveOnly a[] = {1, 2, 3};
2042c3bbac0SNikolas Klauser MoveOnly b[3];
2052c3bbac0SNikolas Klauser std::ranges::move_backward(std::begin(a), std::end(a), std::end(b));
2062c3bbac0SNikolas Klauser assert(b[0].get() == 1);
2072c3bbac0SNikolas Klauser assert(b[1].get() == 2);
2082c3bbac0SNikolas Klauser assert(b[2].get() == 3);
2092c3bbac0SNikolas Klauser }
2106f36ead5SLouis Dionne
2116f36ead5SLouis Dionne // When trivial
2126f36ead5SLouis Dionne {
2136f36ead5SLouis Dionne TrivialMoveOnly a[] = {1, 2, 3};
2146f36ead5SLouis Dionne TrivialMoveOnly b[3];
2156f36ead5SLouis Dionne std::ranges::move_backward(a, std::end(b));
2166f36ead5SLouis Dionne assert(b[0].get() == 1);
2176f36ead5SLouis Dionne assert(b[1].get() == 2);
2186f36ead5SLouis Dionne assert(b[2].get() == 3);
2196f36ead5SLouis Dionne }
2206f36ead5SLouis Dionne {
2216f36ead5SLouis Dionne TrivialMoveOnly a[] = {1, 2, 3};
2226f36ead5SLouis Dionne TrivialMoveOnly b[3];
2236f36ead5SLouis Dionne std::ranges::move_backward(std::begin(a), std::end(a), std::end(b));
2246f36ead5SLouis Dionne assert(b[0].get() == 1);
2256f36ead5SLouis Dionne assert(b[1].get() == 2);
2266f36ead5SLouis Dionne assert(b[2].get() == 3);
2276f36ead5SLouis Dionne }
2282c3bbac0SNikolas Klauser }
2292c3bbac0SNikolas Klauser
230a81cc1fcSHui Xie { // check that a move-only type works for ProxyIterator
231a81cc1fcSHui Xie {
232a81cc1fcSHui Xie MoveOnly a[] = {1, 2, 3};
233a81cc1fcSHui Xie MoveOnly b[3];
234a81cc1fcSHui Xie ProxyRange proxyA{a};
235a81cc1fcSHui Xie ProxyRange proxyB{b};
236a81cc1fcSHui Xie std::ranges::move_backward(proxyA, std::ranges::next(proxyB.begin(), std::end(proxyB)));
237a81cc1fcSHui Xie assert(b[0].get() == 1);
238a81cc1fcSHui Xie assert(b[1].get() == 2);
239a81cc1fcSHui Xie assert(b[2].get() == 3);
240a81cc1fcSHui Xie }
241a81cc1fcSHui Xie {
242a81cc1fcSHui Xie MoveOnly a[] = {1, 2, 3};
243a81cc1fcSHui Xie MoveOnly b[3];
244a81cc1fcSHui Xie ProxyRange proxyA{a};
245a81cc1fcSHui Xie ProxyRange proxyB{b};
246a81cc1fcSHui Xie std::ranges::move_backward(std::begin(proxyA), std::end(proxyA), std::ranges::next(proxyB.begin(), std::end(proxyB)));
247a81cc1fcSHui Xie assert(b[0].get() == 1);
248a81cc1fcSHui Xie assert(b[1].get() == 2);
249a81cc1fcSHui Xie assert(b[2].get() == 3);
250a81cc1fcSHui Xie }
251a81cc1fcSHui Xie }
252a81cc1fcSHui Xie
2532c3bbac0SNikolas Klauser { // check that ranges::dangling is returned
2542c3bbac0SNikolas Klauser std::array<int, 4> out;
2552c3bbac0SNikolas Klauser std::same_as<std::ranges::in_out_result<std::ranges::dangling, int*>> auto ret =
2562c3bbac0SNikolas Klauser std::ranges::move_backward(std::array {1, 2, 3, 4}, out.data() + out.size());
2572c3bbac0SNikolas Klauser assert(ret.out == out.data());
2582c3bbac0SNikolas Klauser assert((out == std::array{1, 2, 3, 4}));
2592c3bbac0SNikolas Klauser }
2602c3bbac0SNikolas Klauser
2612c3bbac0SNikolas Klauser { // check that an iterator is returned with a borrowing range
2622c3bbac0SNikolas Klauser std::array in {1, 2, 3, 4};
2632c3bbac0SNikolas Klauser std::array<int, 4> out;
264*d05bada5SDuo Wang std::same_as<std::ranges::in_out_result<std::array<int, 4>::iterator, int*>> auto ret =
2652c3bbac0SNikolas Klauser std::ranges::move_backward(std::views::all(in), out.data() + out.size());
266*d05bada5SDuo Wang assert(ret.in == in.end());
2672c3bbac0SNikolas Klauser assert(ret.out == out.data());
2682c3bbac0SNikolas Klauser assert(in == out);
2692c3bbac0SNikolas Klauser }
2702c3bbac0SNikolas Klauser
2712c3bbac0SNikolas Klauser { // check that every element is moved exactly once
2722c3bbac0SNikolas Klauser struct MoveOnce {
2732c3bbac0SNikolas Klauser bool moved = false;
2742c3bbac0SNikolas Klauser constexpr MoveOnce() = default;
2752c3bbac0SNikolas Klauser constexpr MoveOnce(const MoveOnce& other) = delete;
2762c3bbac0SNikolas Klauser constexpr MoveOnce& operator=(const MoveOnce& other) {
2772c3bbac0SNikolas Klauser assert(!other.moved);
2782c3bbac0SNikolas Klauser moved = true;
2792c3bbac0SNikolas Klauser return *this;
2802c3bbac0SNikolas Klauser }
2812c3bbac0SNikolas Klauser };
2822c3bbac0SNikolas Klauser {
2832c3bbac0SNikolas Klauser std::array<MoveOnce, 4> in {};
2842c3bbac0SNikolas Klauser std::array<MoveOnce, 4> out {};
2852c3bbac0SNikolas Klauser auto ret = std::ranges::move_backward(in.begin(), in.end(), out.end());
286f537a01dSKonstantin Varlamov assert(ret.in == in.end());
2872c3bbac0SNikolas Klauser assert(ret.out == out.begin());
2882c3bbac0SNikolas Klauser assert(std::all_of(out.begin(), out.end(), [](const auto& e) { return e.moved; }));
2892c3bbac0SNikolas Klauser }
2902c3bbac0SNikolas Klauser {
2912c3bbac0SNikolas Klauser std::array<MoveOnce, 4> in {};
2922c3bbac0SNikolas Klauser std::array<MoveOnce, 4> out {};
2932c3bbac0SNikolas Klauser auto ret = std::ranges::move_backward(in, out.end());
294f537a01dSKonstantin Varlamov assert(ret.in == in.end());
2952c3bbac0SNikolas Klauser assert(ret.out == out.begin());
2962c3bbac0SNikolas Klauser assert(std::all_of(out.begin(), out.end(), [](const auto& e) { return e.moved; }));
2972c3bbac0SNikolas Klauser }
2982c3bbac0SNikolas Klauser }
2992c3bbac0SNikolas Klauser
3002c3bbac0SNikolas Klauser { // check that the range is moved backwards
3012c3bbac0SNikolas Klauser struct OnlyBackwardsMovable {
3022c3bbac0SNikolas Klauser OnlyBackwardsMovable* next = nullptr;
3032c3bbac0SNikolas Klauser bool canMove = false;
3042c3bbac0SNikolas Klauser OnlyBackwardsMovable() = default;
3052c3bbac0SNikolas Klauser constexpr OnlyBackwardsMovable& operator=(const OnlyBackwardsMovable&) {
3062c3bbac0SNikolas Klauser assert(canMove);
3072c3bbac0SNikolas Klauser if (next != nullptr)
3082c3bbac0SNikolas Klauser next->canMove = true;
3092c3bbac0SNikolas Klauser return *this;
3102c3bbac0SNikolas Klauser }
3112c3bbac0SNikolas Klauser };
3122c3bbac0SNikolas Klauser {
3132c3bbac0SNikolas Klauser std::array<OnlyBackwardsMovable, 3> in {};
3142c3bbac0SNikolas Klauser std::array<OnlyBackwardsMovable, 3> out {};
3152c3bbac0SNikolas Klauser out[1].next = &out[0];
3162c3bbac0SNikolas Klauser out[2].next = &out[1];
3172c3bbac0SNikolas Klauser out[2].canMove = true;
3182c3bbac0SNikolas Klauser auto ret = std::ranges::move_backward(in, out.end());
319f537a01dSKonstantin Varlamov assert(ret.in == in.end());
3202c3bbac0SNikolas Klauser assert(ret.out == out.begin());
3212c3bbac0SNikolas Klauser assert(out[0].canMove);
3222c3bbac0SNikolas Klauser assert(out[1].canMove);
3232c3bbac0SNikolas Klauser assert(out[2].canMove);
3242c3bbac0SNikolas Klauser }
3252c3bbac0SNikolas Klauser {
3262c3bbac0SNikolas Klauser std::array<OnlyBackwardsMovable, 3> in {};
3272c3bbac0SNikolas Klauser std::array<OnlyBackwardsMovable, 3> out {};
3282c3bbac0SNikolas Klauser out[1].next = &out[0];
3292c3bbac0SNikolas Klauser out[2].next = &out[1];
3302c3bbac0SNikolas Klauser out[2].canMove = true;
3312c3bbac0SNikolas Klauser auto ret = std::ranges::move_backward(in.begin(), in.end(), out.end());
332f537a01dSKonstantin Varlamov assert(ret.in == in.end());
3332c3bbac0SNikolas Klauser assert(ret.out == out.begin());
3342c3bbac0SNikolas Klauser assert(out[0].canMove);
3352c3bbac0SNikolas Klauser assert(out[1].canMove);
3362c3bbac0SNikolas Klauser assert(out[2].canMove);
3372c3bbac0SNikolas Klauser }
3382c3bbac0SNikolas Klauser }
3392c3bbac0SNikolas Klauser
3402c3bbac0SNikolas Klauser { // check that iter_move is used properly
3412c3bbac0SNikolas Klauser {
3422c3bbac0SNikolas Klauser int a[] = {1, 2, 3, 4};
3432c3bbac0SNikolas Klauser std::array<int, 4> b;
3442c3bbac0SNikolas Klauser auto ret = std::ranges::move_backward(IteratorWithMoveIter(a), IteratorWithMoveIter(a + 4), b.data() + b.size());
345f537a01dSKonstantin Varlamov assert(ret.in == a + 4);
3462c3bbac0SNikolas Klauser assert(ret.out == b.data());
3472c3bbac0SNikolas Klauser assert((b == std::array {42, 42, 42, 42}));
3482c3bbac0SNikolas Klauser }
3492c3bbac0SNikolas Klauser {
3502c3bbac0SNikolas Klauser int a[] = {1, 2, 3, 4};
3512c3bbac0SNikolas Klauser std::array<int, 4> b;
3522c3bbac0SNikolas Klauser auto range = std::ranges::subrange(IteratorWithMoveIter(a), IteratorWithMoveIter(a + 4));
3532c3bbac0SNikolas Klauser auto ret = std::ranges::move_backward(range, b.data() + b.size());
354f537a01dSKonstantin Varlamov assert(ret.in == a + 4);
3552c3bbac0SNikolas Klauser assert(ret.out == b.data());
3562c3bbac0SNikolas Klauser assert((b == std::array {42, 42, 42, 42}));
3572c3bbac0SNikolas Klauser }
3582c3bbac0SNikolas Klauser }
3592c3bbac0SNikolas Klauser
3602c3bbac0SNikolas Klauser return true;
3612c3bbac0SNikolas Klauser }
3622c3bbac0SNikolas Klauser
main(int,char **)3632c3bbac0SNikolas Klauser int main(int, char**) {
3642c3bbac0SNikolas Klauser test();
3652c3bbac0SNikolas Klauser static_assert(test());
3662c3bbac0SNikolas Klauser
3672c3bbac0SNikolas Klauser return 0;
3682c3bbac0SNikolas Klauser }
369