1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // UNSUPPORTED: c++03 && !stdlib=libc++ |
10 | |
11 | // <algorithm> |
12 | |
13 | // template<BidirectionalIterator InIter, BidirectionalIterator OutIter> |
14 | // requires OutputIterator<OutIter, RvalueOf<InIter::reference>::type> |
15 | // OutIter |
16 | // move_backward(InIter first, InIter last, OutIter result); |
17 | |
18 | #include <algorithm> |
19 | #include <cassert> |
20 | #include <iterator> |
21 | #include <memory> |
22 | |
23 | #include "MoveOnly.h" |
24 | #include "test_iterators.h" |
25 | #include "test_macros.h" |
26 | |
27 | class PaddedBase { |
28 | public: |
29 | TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {} |
30 | |
31 | std::int16_t a_; |
32 | std::int8_t b_; |
33 | }; |
34 | |
35 | class Derived : public PaddedBase { |
36 | public: |
37 | TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {} |
38 | |
39 | std::int8_t c_; |
40 | }; |
41 | |
42 | template <class InIter> |
43 | struct Test { |
44 | template <class OutIter> |
45 | TEST_CONSTEXPR_CXX20 void operator()() { |
46 | const unsigned N = 1000; |
47 | int ia[N] = {}; |
48 | for (unsigned i = 0; i < N; ++i) |
49 | ia[i] = i; |
50 | int ib[N] = {0}; |
51 | |
52 | OutIter r = std::move_backward(InIter(ia), InIter(ia+N), OutIter(ib+N)); |
53 | assert(base(r) == ib); |
54 | for (unsigned i = 0; i < N; ++i) |
55 | assert(ia[i] == ib[i]); |
56 | } |
57 | }; |
58 | |
59 | struct TestOutIters { |
60 | template <class InIter> |
61 | TEST_CONSTEXPR_CXX20 void operator()() { |
62 | types::for_each( |
63 | types::concatenate_t<types::bidirectional_iterator_list<int*> >(), |
64 | Test<InIter>()); |
65 | } |
66 | }; |
67 | |
68 | template <class InIter> |
69 | struct Test1 { |
70 | template <class OutIter> |
71 | TEST_CONSTEXPR_CXX23 void operator()() { |
72 | const unsigned N = 100; |
73 | std::unique_ptr<int> ia[N]; |
74 | for (unsigned i = 0; i < N; ++i) |
75 | ia[i].reset(p: new int(i)); |
76 | std::unique_ptr<int> ib[N]; |
77 | |
78 | OutIter r = std::move_backward(InIter(ia), InIter(ia+N), OutIter(ib+N)); |
79 | assert(base(r) == ib); |
80 | for (unsigned i = 0; i < N; ++i) |
81 | assert(*ib[i] == static_cast<int>(i)); |
82 | } |
83 | }; |
84 | |
85 | struct Test1OutIters { |
86 | template <class InIter> |
87 | TEST_CONSTEXPR_CXX23 void operator()() { |
88 | types::for_each(types::concatenate_t<types::bidirectional_iterator_list<std::unique_ptr<int>*> >(), |
89 | Test1<InIter>()); |
90 | } |
91 | }; |
92 | |
93 | TEST_CONSTEXPR_CXX20 bool test() { |
94 | types::for_each(types::bidirectional_iterator_list<int*>(), TestOutIters()); |
95 | if (TEST_STD_AT_LEAST_23_OR_RUNTIME_EVALUATED) |
96 | types::for_each(types::bidirectional_iterator_list<std::unique_ptr<int>*>(), Test1OutIters()); |
97 | |
98 | { // Make sure that padding bits aren't copied |
99 | Derived src(1, 2, 3); |
100 | Derived dst(4, 5, 6); |
101 | std::move_backward( |
102 | first: static_cast<PaddedBase*>(&src), last: static_cast<PaddedBase*>(&src) + 1, result: static_cast<PaddedBase*>(&dst) + 1); |
103 | assert(dst.a_ == 1); |
104 | assert(dst.b_ == 2); |
105 | assert(dst.c_ == 6); |
106 | } |
107 | |
108 | { // Make sure that overlapping ranges can be copied |
109 | int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; |
110 | std::move_backward(first: a, last: a + 7, result: a + 10); |
111 | int expected[] = {1, 2, 3, 1, 2, 3, 4, 5, 6, 7}; |
112 | assert(std::equal(a, a + 10, expected)); |
113 | } |
114 | |
115 | // Make sure that the algorithm works with move-only types |
116 | { |
117 | // When non-trivial |
118 | { |
119 | MoveOnly from[3] = {1, 2, 3}; |
120 | MoveOnly to[3] = {}; |
121 | std::move_backward(std::begin(from), std::end(from), std::end(to)); |
122 | assert(to[0] == MoveOnly(1)); |
123 | assert(to[1] == MoveOnly(2)); |
124 | assert(to[2] == MoveOnly(3)); |
125 | } |
126 | // When trivial |
127 | { |
128 | TrivialMoveOnly from[3] = {1, 2, 3}; |
129 | TrivialMoveOnly to[3] = {}; |
130 | std::move_backward(std::begin(from), std::end(from), std::end(to)); |
131 | assert(to[0] == TrivialMoveOnly(1)); |
132 | assert(to[1] == TrivialMoveOnly(2)); |
133 | assert(to[2] == TrivialMoveOnly(3)); |
134 | } |
135 | } |
136 | |
137 | return true; |
138 | } |
139 | |
140 | int main(int, char**) |
141 | { |
142 | test(); |
143 | #if TEST_STD_VER >= 20 |
144 | static_assert(test()); |
145 | #endif |
146 | |
147 | return 0; |
148 | } |
149 | |