kblib 0.2.3
General utilities library for modern C++
memory.cpp
Go to the documentation of this file.
1#include "kblib/memory.h"
2
3#include "catch.hpp"
4#include "kblib/fakestd.h"
5
6TEST_CASE("live_ptr<int>") {
7 // default-initialized live_ptrs are null
9 REQUIRE(not dptr);
10 // can be compared to nullptr
11 REQUIRE(dptr == nullptr);
12
13 // obtain a live_ptr to an object
15 auto ptr = obj->ref();
16 REQUIRE(ptr);
17 REQUIRE(ptr != dptr);
18
19 // access through the pointer
20 REQUIRE(obj->data == *ptr);
21 ++*ptr;
22 REQUIRE(obj->data == *ptr);
23
24 // can be compared with a raw pointer
25 REQUIRE(ptr == &obj->data);
26
27 // copy the pointer
28 auto ptr2 = ptr;
29 REQUIRE(ptr == ptr2);
30
31 // move the pointer
32 auto ptr3 = std::move(ptr2);
33 REQUIRE(ptr3 == ptr);
34 REQUIRE(not ptr2);
35
36 // reassign a pointer
37 ptr2 = ptr3;
38
39 // implicitly add const
41 REQUIRE(cptr == ptr);
42
43 auto cptr2 = cptr;
44 REQUIRE(cptr2 == ptr);
45 auto cptr3 = std::move(cptr2);
46 REQUIRE(not cptr2);
47
48 // destroy the referenced object
49 obj.reset();
50
51 // all pointers to it are now null
52 REQUIRE(not ptr);
53 REQUIRE(ptr == ptr3);
54 REQUIRE(ptr == dptr);
55 REQUIRE(not cptr);
56}
57
58TEST_CASE("live_ptr<string>") {
59 // default-initialized live_ptrs are null
61 REQUIRE(not dptr);
62 // can be compared to nullptr
63 REQUIRE(dptr == nullptr);
64
65 // obtain a live_ptr to an object
67 auto ptr = obj->ref();
68 REQUIRE(ptr);
69 REQUIRE(ptr != dptr);
70
71 // access through the pointer
72 REQUIRE(obj->data == *ptr);
73 REQUIRE(ptr->length() == 0);
74 *ptr = "test";
75 REQUIRE(obj->data == *ptr);
76 REQUIRE(ptr->length() == 4);
77
78 // can be compared with a raw pointer
79 REQUIRE(ptr == &obj->data);
80
81 // copy the pointer
82 auto ptr2 = ptr;
83 REQUIRE(ptr == ptr2);
84
85 // move the pointer
86 auto ptr3 = std::move(ptr2);
87 REQUIRE(ptr3 == ptr);
88 REQUIRE(not ptr2);
89
90 // reassign a pointer
91 ptr2 = ptr3;
92
93 // implicitly add const
95 REQUIRE(cptr == ptr);
96
97 auto cptr2 = cptr;
98 REQUIRE(cptr2 == ptr);
99 auto cptr3 = std::move(cptr2);
100 REQUIRE(not cptr2);
101
102 // destroy the referenced object
103 obj.reset();
104
105 // all pointers to it are now null
106 REQUIRE(not ptr);
107 REQUIRE(ptr == ptr3);
108 REQUIRE(ptr == dptr);
109 REQUIRE(not cptr);
110}
111
112TEST_CASE("cond_ptr") {
113 int a{42};
114 auto op = kblib::make_cond_ptr(std::make_unique<int>(42));
115 auto rp = kblib::make_cond_ptr(&a);
116 REQUIRE(op);
117 REQUIRE(rp);
118 REQUIRE(*op == *rp);
119 REQUIRE(op.owns());
120 REQUIRE_FALSE(rp.owns());
121 auto cp = op.weak();
122 REQUIRE(cp);
123 REQUIRE(cp == op);
124 REQUIRE(op.owns());
125 REQUIRE_FALSE(cp.owns());
126 auto up = std::unique_ptr<int>(std::move(rp));
127 REQUIRE_FALSE(up);
128 up = std::move(op).to_unique();
129 REQUIRE(up == cp);
130 REQUIRE(up);
131 op.reset(up.release(), true);
132 REQUIRE(cp == op);
133 rp = std::move(up);
134 REQUIRE_FALSE(rp);
135 REQUIRE_FALSE(rp.owns());
136}
137
138TEST_CASE("cond_ptr fptr") {
139 auto del = [](kblib::owner<const int*> p) noexcept { delete p; };
140 int a{42};
142 std::unique_ptr<int, decltype(+del)>(new int{42}, del));
144 REQUIRE(op);
145 REQUIRE(rp);
146 REQUIRE(*op == *rp);
147 REQUIRE(op.owns());
148 REQUIRE_FALSE(rp.owns());
149 auto cp = op.weak();
150 REQUIRE(cp);
151 REQUIRE(cp == op);
152 REQUIRE(op.owns());
153 REQUIRE_FALSE(cp.owns());
154 auto up = std::unique_ptr<int, decltype(+del)>(std::move(rp));
155 REQUIRE_FALSE(up);
156 up = std::move(op).to_unique();
157 REQUIRE(up == cp);
158 REQUIRE(up);
159 op.reset(up.release(), true, up.get_deleter());
160 REQUIRE(cp == op);
161 rp = std::move(up);
162 REQUIRE_FALSE(rp);
163 REQUIRE_FALSE(rp.owns());
164}
165
166TEST_CASE("cond_ptr rfptr") {
167 auto del = [](kblib::owner<const int*> p) noexcept { delete p; };
168 int a{42};
170 std::unique_ptr<int, decltype(*+del)>(new int{42}, *del));
172 REQUIRE(op);
173 REQUIRE(rp);
174 REQUIRE(*op == *rp);
175 REQUIRE(op.owns());
176 REQUIRE_FALSE(rp.owns());
177 auto cp = op.weak();
178 REQUIRE(cp);
179 REQUIRE(cp == op);
180 REQUIRE(op.owns());
181 REQUIRE_FALSE(cp.owns());
182 auto up = std::unique_ptr<int, decltype(*+del)>(std::move(rp));
183 REQUIRE_FALSE(up);
184}
185
186TEST_CASE("cond_ptr array") {
187 int a[10]{42};
188 auto op = kblib::make_cond_ptr(std::make_unique<int[]>(42));
189 auto rp = kblib::cond_ptr<int[]>(a);
190 REQUIRE(op);
191 REQUIRE(rp);
192 REQUIRE_FALSE(op == rp);
193 REQUIRE(op.owns());
194 REQUIRE_FALSE(rp.owns());
195 auto cp = op.weak();
196 REQUIRE(cp);
197 REQUIRE(cp == op);
198 REQUIRE(op.owns());
199 REQUIRE_FALSE(cp.owns());
200 auto up = std::unique_ptr<int[]>(std::move(rp));
201 REQUIRE_FALSE(up);
202 up = std::move(op).to_unique();
203 REQUIRE(up == cp);
204 REQUIRE(up);
205 op.reset(up.release(), true);
206 REQUIRE(cp == op);
207 rp = std::move(up);
208 REQUIRE_FALSE(rp);
209 REQUIRE_FALSE(rp.owns());
210}
This header provides some features of C++17 <type_traits> and other headers for C++14,...
TEST_CASE("live_ptr<int>")
Definition: memory.cpp:6
Provides utilities to enable safe and expressive memory management and low-level memory manipulation.
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
Definition: simple.h:255
T owner
Definition: fakestd.h:57
auto make_cond_ptr(std::unique_ptr< T, Deleter > &&arg) noexcept -> cond_ptr< T, Deleter >
Definition: memory.h:783
auto to_unique(owner< T * > p) -> std::unique_ptr< T >
Definition: fakestd.h:580