xref: /llvm-project/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp (revision c4e98722ca79c827dd57b809e0ef16b3b8da8c72)
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 <memory>
21 
22 #include "test_macros.h"
23 #include "test_iterators.h"
24 
25 class PaddedBase {
26 public:
27   TEST_CONSTEXPR PaddedBase(std::int16_t a, std::int8_t b) : a_(a), b_(b) {}
28 
29   std::int16_t a_;
30   std::int8_t b_;
31 };
32 
33 class Derived : public PaddedBase {
34 public:
35   TEST_CONSTEXPR Derived(std::int16_t a, std::int8_t b, std::int8_t c) : PaddedBase(a, b), c_(c) {}
36 
37   std::int8_t c_;
38 };
39 
40 template <class InIter>
41 struct Test {
42   template <class OutIter>
43   TEST_CONSTEXPR_CXX20 void operator()() {
44     const unsigned N = 1000;
45     int ia[N] = {};
46     for (unsigned i = 0; i < N; ++i)
47         ia[i] = i;
48     int ib[N] = {0};
49 
50     OutIter r = std::move_backward(InIter(ia), InIter(ia+N), OutIter(ib+N));
51     assert(base(r) == ib);
52     for (unsigned i = 0; i < N; ++i)
53         assert(ia[i] == ib[i]);
54   }
55 };
56 
57 struct TestOutIters {
58   template <class InIter>
59   TEST_CONSTEXPR_CXX20 void operator()() {
60     types::for_each(
61         types::concatenate_t<types::bidirectional_iterator_list<int*> >(),
62         Test<InIter>());
63   }
64 };
65 
66 template <class InIter>
67 struct Test1 {
68   template <class OutIter>
69   TEST_CONSTEXPR_CXX23 void operator()() {
70     const unsigned N = 100;
71     std::unique_ptr<int> ia[N];
72     for (unsigned i = 0; i < N; ++i)
73         ia[i].reset(new int(i));
74     std::unique_ptr<int> ib[N];
75 
76     OutIter r = std::move_backward(InIter(ia), InIter(ia+N), OutIter(ib+N));
77     assert(base(r) == ib);
78     for (unsigned i = 0; i < N; ++i)
79         assert(*ib[i] == static_cast<int>(i));
80   }
81 };
82 
83 struct Test1OutIters {
84   template <class InIter>
85   TEST_CONSTEXPR_CXX23 void operator()() {
86     types::for_each(types::concatenate_t<types::bidirectional_iterator_list<std::unique_ptr<int>*> >(),
87                     Test1<InIter>());
88   }
89 };
90 
91 TEST_CONSTEXPR_CXX20 bool test() {
92   types::for_each(types::bidirectional_iterator_list<int*>(), TestOutIters());
93   if (TEST_STD_VER >= 23 || !TEST_IS_CONSTANT_EVALUATED)
94     types::for_each(types::bidirectional_iterator_list<std::unique_ptr<int>*>(), Test1OutIters());
95 
96   { // Make sure that padding bits aren't copied
97     Derived src(1, 2, 3);
98     Derived dst(4, 5, 6);
99     std::move_backward(
100         static_cast<PaddedBase*>(&src), static_cast<PaddedBase*>(&src) + 1, static_cast<PaddedBase*>(&dst) + 1);
101     assert(dst.a_ == 1);
102     assert(dst.b_ == 2);
103     assert(dst.c_ == 6);
104   }
105 
106   { // Make sure that overlapping ranges can be copied
107     int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
108     std::move_backward(a, a + 7, a + 10);
109     int expected[] = {1, 2, 3, 1, 2, 3, 4, 5, 6, 7};
110     assert(std::equal(a, a + 10, expected));
111   }
112 
113   return true;
114 }
115 
116 int main(int, char**)
117 {
118   test();
119 #if TEST_STD_VER >= 20
120   static_assert(test());
121 #endif
122 
123   return 0;
124 }
125