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, c++11, c++14
10
11// <memory>
12
13// template <class InputIt, class Size, class ForwardIt>
14// pair<InputIt, ForwardIt> uninitialized_move_n(InputIt, Size, ForwardIt);
15
16#include <memory>
17#include <cstdlib>
18#include <cassert>
19
20#include "test_macros.h"
21#include "test_iterators.h"
22#include "../overload_compare_iterator.h"
23
24struct Counted {
25 static int count;
26 static int constructed;
27 static void reset() { count = constructed = 0; }
28 explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; }
29 Counted(Counted const&) { assert(false); }
30 ~Counted() { assert(count > 0); --count; }
31 friend void operator&(Counted) = delete;
32 int value;
33};
34int Counted::count = 0;
35int Counted::constructed = 0;
36
37struct ThrowsCounted {
38 static int count;
39 static int constructed;
40 static int throw_after;
41 static void reset() { throw_after = count = constructed = 0; }
42 explicit ThrowsCounted(int&& x) {
43 ++constructed;
44 if (throw_after > 0 && --throw_after == 0) {
45 TEST_THROW(1);
46 }
47 ++count;
48 x = 0;
49 }
50 ThrowsCounted(ThrowsCounted const&) { assert(false); }
51 ~ThrowsCounted() { assert(count > 0); --count; }
52 friend void operator&(ThrowsCounted) = delete;
53};
54int ThrowsCounted::count = 0;
55int ThrowsCounted::constructed = 0;
56int ThrowsCounted::throw_after = 0;
57
58void test_ctor_throws()
59{
60#ifndef TEST_HAS_NO_EXCEPTIONS
61 using It = forward_iterator<ThrowsCounted*>;
62 const int N = 5;
63 int values[N] = {1, 2, 3, 4, 5};
64 alignas(ThrowsCounted) char pool[sizeof(ThrowsCounted)*N] = {};
65 ThrowsCounted* p = (ThrowsCounted*)pool;
66 try {
67 ThrowsCounted::throw_after = 4;
68 std::uninitialized_move_n(values, N, It(p));
69 assert(false);
70 } catch (...) {}
71 assert(ThrowsCounted::count == 0);
72 assert(ThrowsCounted::constructed == 4); // forth construction throws
73 assert(values[0] == 0);
74 assert(values[1] == 0);
75 assert(values[2] == 0);
76 assert(values[3] == 4);
77 assert(values[4] == 5);
78#endif
79}
80
81void test_counted()
82{
83 using It = cpp17_input_iterator<int*>;
84 using FIt = forward_iterator<Counted*>;
85 const int N = 5;
86 int values[N] = {1, 2, 3, 4, 5};
87 alignas(Counted) char pool[sizeof(Counted)*N] = {};
88 Counted* p = (Counted*)pool;
89 auto ret = std::uninitialized_move_n(It(values), 1, FIt(p));
90 assert(ret.first == It(values +1));
91 assert(ret.second == FIt(p +1));
92 assert(Counted::constructed == 1);
93 assert(Counted::count == 1);
94 assert(p[0].value == 1);
95 assert(values[0] == 0);
96 ret = std::uninitialized_move_n(It(values+1), N-1, FIt(p+1));
97 assert(ret.first == It(values+N));
98 assert(ret.second == FIt(p + N));
99 assert(Counted::count == 5);
100 assert(Counted::constructed == 5);
101 assert(p[1].value == 2);
102 assert(p[2].value == 3);
103 assert(p[3].value == 4);
104 assert(p[4].value == 5);
105 assert(values[1] == 0);
106 assert(values[2] == 0);
107 assert(values[3] == 0);
108 assert(values[4] == 0);
109 std::destroy(first: p, last: p+N);
110 assert(Counted::count == 0);
111}
112
113int main(int, char**)
114{
115 test_counted();
116 test_ctor_throws();
117
118 // Test with an iterator that overloads operator== and operator!= as the input and output iterators
119 {
120 using T = int;
121 using Iterator = overload_compare_iterator<T*>;
122 const int N = 5;
123
124 // input
125 {
126 char pool[sizeof(T) * N] = {0};
127 T* p = reinterpret_cast<T*>(pool);
128 T array[N] = {1, 2, 3, 4, 5};
129 std::uninitialized_move_n(Iterator(array), N, p);
130 for (int i = 0; i != N; ++i) {
131 assert(array[i] == p[i]);
132 }
133 }
134
135 // output
136 {
137 char pool[sizeof(T) * N] = {0};
138 T* p = reinterpret_cast<T*>(pool);
139 T array[N] = {1, 2, 3, 4, 5};
140 std::uninitialized_move_n(array, N, Iterator(p));
141 for (int i = 0; i != N; ++i) {
142 assert(array[i] == p[i]);
143 }
144 }
145 }
146
147 return 0;
148}
149

source code of libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp