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, c++17, c++20
10
11// <memory>
12
13// [out.ptr], function template out_ptr
14// template<class Pointer = void, class Smart, class... Args>
15// auto out_ptr(Smart& s, Args&&... args); // since c++23
16
17#include <cassert>
18#include <memory>
19#include <utility>
20
21#include "../types.h"
22
23// Test updating an `out_ptr_t`-managed pointer for an API with a non-void pointer type.
24// The API returns a new valid object.
25void test_get_int_p() {
26 auto get_int_p = [](int** pp) { *pp = new int{84}; };
27
28 // raw pointer
29 {
30 int* rPtr;
31
32 get_int_p(std::out_ptr<int*>(rPtr));
33 assert(*rPtr == 84);
34
35 delete rPtr;
36 }
37
38 // std::unique_ptr
39 {
40 std::unique_ptr<int> uPtr;
41
42 get_int_p(std::out_ptr(uPtr));
43 assert(*uPtr == 84);
44 }
45
46 {
47 MoveOnlyDeleter<int> del;
48 std::unique_ptr<int, MoveOnlyDeleter<int>> uPtr;
49
50 get_int_p(std::out_ptr(uPtr, std::move(del)));
51 assert(*uPtr == 84);
52 assert(uPtr.get_deleter().wasMoveInitilized == true);
53 }
54
55 // std::shared_ptr
56 {
57 std::shared_ptr<int> sPtr;
58
59 get_int_p(std::out_ptr(sPtr, [](auto* p) {
60 assert(*p == 84);
61
62 delete p;
63 }));
64 assert(*sPtr == 84);
65 }
66
67 // pointer-like ConstructiblePtr
68 {
69 ConstructiblePtr<int> cPtr;
70
71 get_int_p(std::out_ptr(cPtr));
72 assert(cPtr == 84);
73 }
74
75 // pointer-like ResettablePtr
76 {
77 ResettablePtr<int> rPtr{nullptr};
78
79 get_int_p(std::out_ptr(rPtr));
80 assert(rPtr == 84);
81 }
82
83 // NonConstructiblePtr
84 {
85 NonConstructiblePtr<int> nPtr;
86
87 get_int_p(std::out_ptr(nPtr));
88 assert(nPtr == 84);
89 }
90}
91
92// Test updating an `out_ptr_t`-managed pointer for an API with a non-void pointer type.
93// The API returns `nullptr`.
94void test_get_int_p_nullptr() {
95 auto get_int_p_nullptr = [](int** pp) { *pp = nullptr; };
96 // raw pointer
97 {
98 int* rPtr;
99
100 get_int_p_nullptr(std::out_ptr<int*>(rPtr));
101 assert(rPtr == nullptr);
102
103 delete rPtr;
104 }
105
106 // std::unique_ptr
107 {
108 std::unique_ptr<int> uPtr;
109
110 get_int_p_nullptr(std::out_ptr(uPtr));
111 assert(uPtr == nullptr);
112 }
113
114 // std::shared_ptr
115 {
116 std::shared_ptr<int> sPtr;
117
118 get_int_p_nullptr(std::out_ptr(sPtr, [](auto* p) {
119 assert(p == nullptr);
120
121 delete p;
122 }));
123 assert(sPtr == nullptr);
124 }
125}
126
127// Test updating an `out_ptr_t`-managed pointer for an API with a void pointer type.
128// The API returns a new valid object.
129void test_get_int_void_p() {
130 auto get_int_void_p = [](void** pp) { *(reinterpret_cast<int**>(pp)) = new int{84}; };
131
132 // raw pointer
133 {
134 int* rPtr;
135
136 get_int_void_p(std::out_ptr(rPtr));
137 assert(*rPtr == 84);
138
139 delete rPtr;
140 }
141
142 // std::unique_ptr
143 {
144 std::unique_ptr<int> uPtr;
145
146 get_int_void_p(std::out_ptr(uPtr));
147 assert(*uPtr == 84);
148 }
149
150 // std::shared_ptr
151 {
152 std::shared_ptr<int> sPtr;
153
154 get_int_void_p(std::out_ptr(sPtr, [](auto* p) {
155 assert(*p == 84);
156
157 delete p;
158 }));
159 assert(*sPtr == 84);
160 }
161
162 // pointer-like ConstructiblePtr
163 {
164 ConstructiblePtr<int> cPtr;
165
166 get_int_void_p(std::out_ptr(cPtr));
167 assert(cPtr == 84);
168 }
169
170 // pointer-like ResettablePtr
171 {
172 ResettablePtr<int> rPtr{nullptr};
173
174 get_int_void_p(std::out_ptr(rPtr));
175 assert(rPtr == 84);
176 }
177
178 // NonConstructiblePtr
179 {
180 NonConstructiblePtr<int> nPtr;
181
182 get_int_void_p(std::out_ptr(nPtr));
183 assert(nPtr == 84);
184 }
185}
186
187// Test updating an `out_ptr_t`-managed pointer for an API with a void pointer type.
188// The API returns `nullptr`.
189void test_get_int_void_p_nullptr() {
190 auto get_int_void_p_nullptr = [](void** pp) { *pp = nullptr; };
191
192 // raw pointer
193 {
194 int* rPtr;
195
196 get_int_void_p_nullptr(std::out_ptr<int*>(rPtr));
197 assert(rPtr == nullptr);
198
199 delete rPtr;
200 }
201
202 // std::unique_ptr
203 {
204 std::unique_ptr<int> uPtr;
205
206 get_int_void_p_nullptr(std::out_ptr(uPtr));
207 assert(uPtr == nullptr);
208 }
209
210 // std::shared_ptr
211 {
212 std::shared_ptr<int> sPtr;
213
214 get_int_void_p_nullptr(std::out_ptr(sPtr, [](auto* p) {
215 assert(p == nullptr);
216
217 delete p;
218 }));
219 assert(sPtr == nullptr);
220 }
221}
222
223int main(int, char**) {
224 test_get_int_p();
225 test_get_int_p_nullptr();
226 test_get_int_void_p();
227 test_get_int_void_p_nullptr();
228
229 return 0;
230}
231

source code of libcxx/test/std/utilities/smartptr/adapt/out_ptr/out_ptr.general.pass.cpp