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// <memory>
10
11// unique_ptr
12
13// Test unique_ptr move ctor
14
15#include <memory>
16#include <utility>
17#include <cassert>
18
19#include "test_macros.h"
20#include "unique_ptr_test_helper.h"
21
22//=============================================================================
23// TESTING unique_ptr(unique_ptr&&)
24//
25// Concerns
26// 1 The moved from pointer is empty and the new pointer stores the old value.
27// 2 The only requirement on the deleter is that it is MoveConstructible
28// or a reference.
29// 3 The constructor works for explicitly moved values (i.e. std::move(x))
30// 4 The constructor works for true temporaries (e.g. a return value)
31//
32// Plan
33// 1 Explicitly construct unique_ptr<T, D> for various deleter types 'D'.
34// check that the value and deleter have been properly moved. (C-1,2,3)
35//
36// 2 Use the expression 'sink(source())' to move construct a unique_ptr<T, D>
37// from a temporary. 'source' should return the unique_ptr by value and
38// 'sink' should accept the unique_ptr by value. (C-1,2,4)
39
40template <class VT>
41TEST_CONSTEXPR_CXX23 std::unique_ptr<VT> source1() {
42 return std::unique_ptr<VT>(newValue<VT>(1));
43}
44
45template <class VT>
46TEST_CONSTEXPR_CXX23 std::unique_ptr<VT, Deleter<VT> > source2() {
47 return std::unique_ptr<VT, Deleter<VT> >(newValue<VT>(1), Deleter<VT>(5));
48}
49
50template <class VT>
51std::unique_ptr<VT, NCDeleter<VT>&> source3() {
52 static NCDeleter<VT> d(5);
53 return std::unique_ptr<VT, NCDeleter<VT>&>(newValue<VT>(1), d);
54}
55
56template <class VT>
57TEST_CONSTEXPR_CXX23 void sink1(std::unique_ptr<VT> p) {
58 assert(p.get() != nullptr);
59}
60
61template <class VT>
62TEST_CONSTEXPR_CXX23 void sink2(std::unique_ptr<VT, Deleter<VT> > p) {
63 assert(p.get() != nullptr);
64 assert(p.get_deleter().state() == 5);
65}
66
67template <class VT>
68void sink3(std::unique_ptr<VT, NCDeleter<VT>&> p) {
69 assert(p.get() != nullptr);
70 assert(p.get_deleter().state() == 5);
71 assert(&p.get_deleter() == &source3<VT>().get_deleter());
72}
73
74template <class ValueT>
75TEST_CONSTEXPR_CXX23 void test_sfinae() {
76 typedef std::unique_ptr<ValueT> U;
77 { // Ensure unique_ptr is non-copyable
78 static_assert((!std::is_constructible<U, U const&>::value), "");
79 static_assert((!std::is_constructible<U, U&>::value), "");
80 }
81}
82
83template <bool IsArray>
84TEST_CONSTEXPR_CXX23 void test_basic() {
85 typedef typename std::conditional<!IsArray, A, A[]>::type VT;
86 const int expect_alive = IsArray ? 5 : 1;
87 {
88 typedef std::unique_ptr<VT> APtr;
89 APtr s(newValue<VT>(expect_alive));
90 A* p = s.get();
91 APtr s2 = std::move(s);
92 assert(s2.get() == p);
93 assert(s.get() == 0);
94 if (!TEST_IS_CONSTANT_EVALUATED)
95 assert(A::count == expect_alive);
96 }
97 if (!TEST_IS_CONSTANT_EVALUATED)
98 assert(A::count == 0);
99 {
100 typedef Deleter<VT> MoveDel;
101 typedef std::unique_ptr<VT, MoveDel> APtr;
102 MoveDel d(5);
103 APtr s(newValue<VT>(expect_alive), std::move(d));
104 assert(d.state() == 0);
105 assert(s.get_deleter().state() == 5);
106 A* p = s.get();
107 APtr s2 = std::move(s);
108 assert(s2.get() == p);
109 assert(s.get() == 0);
110 if (!TEST_IS_CONSTANT_EVALUATED)
111 assert(A::count == expect_alive);
112 assert(s2.get_deleter().state() == 5);
113 assert(s.get_deleter().state() == 0);
114 }
115 if (!TEST_IS_CONSTANT_EVALUATED)
116 assert(A::count == 0);
117 {
118 typedef NCDeleter<VT> NonCopyDel;
119 typedef std::unique_ptr<VT, NonCopyDel&> APtr;
120
121 NonCopyDel d;
122 APtr s(newValue<VT>(expect_alive), d);
123 A* p = s.get();
124 APtr s2 = std::move(s);
125 assert(s2.get() == p);
126 assert(s.get() == 0);
127 if (!TEST_IS_CONSTANT_EVALUATED)
128 assert(A::count == expect_alive);
129 d.set_state(6);
130 assert(s2.get_deleter().state() == d.state());
131 assert(s.get_deleter().state() == d.state());
132 }
133 if (!TEST_IS_CONSTANT_EVALUATED)
134 assert(A::count == 0);
135 {
136 sink1<VT>(source1<VT>());
137 if (!TEST_IS_CONSTANT_EVALUATED)
138 assert(A::count == 0);
139 sink2<VT>(source2<VT>());
140 if (!TEST_IS_CONSTANT_EVALUATED)
141 assert(A::count == 0);
142 }
143 if (!TEST_IS_CONSTANT_EVALUATED)
144 assert(A::count == 0);
145}
146
147template <class VT>
148TEST_CONSTEXPR_CXX23 void test_noexcept() {
149#if TEST_STD_VER >= 11
150 {
151 typedef std::unique_ptr<VT> U;
152 static_assert(std::is_nothrow_move_constructible<U>::value, "");
153 }
154 {
155 typedef std::unique_ptr<VT, Deleter<VT> > U;
156 static_assert(std::is_nothrow_move_constructible<U>::value, "");
157 }
158 {
159 typedef std::unique_ptr<VT, NCDeleter<VT> &> U;
160 static_assert(std::is_nothrow_move_constructible<U>::value, "");
161 }
162 {
163 typedef std::unique_ptr<VT, const NCConstDeleter<VT> &> U;
164 static_assert(std::is_nothrow_move_constructible<U>::value, "");
165 }
166#endif
167}
168
169TEST_CONSTEXPR_CXX23 bool test() {
170 {
171 test_basic</*IsArray*/ false>();
172 test_sfinae<int>();
173 test_noexcept<int>();
174 }
175 {
176 test_basic</*IsArray*/ true>();
177 test_sfinae<int[]>();
178 test_noexcept<int[]>();
179 }
180
181 return true;
182}
183
184template <bool IsArray>
185void test_sink3() {
186 typedef typename std::conditional<!IsArray, A, A[]>::type VT;
187 sink3<VT>(source3<VT>());
188 assert(A::count == 0);
189}
190
191int main(int, char**) {
192 test_sink3</*IsArray*/ false>();
193 test_sink3</*IsArray*/ true>();
194 test();
195#if TEST_STD_VER >= 23
196 static_assert(test());
197#endif
198
199 return 0;
200}
201

source code of libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/move.pass.cpp