Skip to content

Commit 48b703b

Browse files
authored
Minor cleanup/improvements in unique_ptr_test (#1266)
I'd previously introduced a bunch of small wrappers around the class and functions under test to avoid excessive cpp use, but we can achieve this more expediently with simple using-declarations. This also cuts out some over-specified tests (e.g. there's no reason a stateful deleter wouldn't compile.)
1 parent 389d565 commit 48b703b

File tree

1 file changed

+69
-60
lines changed

1 file changed

+69
-60
lines changed

test/ctl/unique_ptr_test.cc

Lines changed: 69 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -24,72 +24,56 @@
2424
// #include <type_traits>
2525
// #define ctl std
2626

27-
template<typename T, typename D = ctl::default_delete<T>>
28-
using Ptr = ctl::unique_ptr<T, D>;
27+
using ctl::unique_ptr;
28+
using ctl::make_unique;
29+
using ctl::make_unique_for_overwrite;
2930

30-
template<typename T, typename... Args>
31-
Ptr<T>
32-
Mk(Args&&... args)
33-
{
34-
return ctl::make_unique<T, Args...>(ctl::forward<Args>(args)...);
35-
}
36-
37-
template<typename T>
38-
Ptr<T>
39-
MkRaw()
40-
{
41-
return ctl::make_unique_for_overwrite<T>();
42-
}
43-
44-
// #undef ctl
31+
#undef ctl
4532

33+
// The following few definitions are used to get observability into aspects of
34+
// an object's lifecycle, to make sure that e.g. constructing a unique_ptr of a
35+
// type does not construct an object, and that make_unique does construct an
36+
// object.
4637
static int g = 0;
4738

48-
struct SetsGDeleter
39+
struct ConstructG
4940
{
50-
void operator()(auto* x) const noexcept
41+
ConstructG()
5142
{
5243
++g;
53-
delete x;
5444
}
5545
};
5646

57-
struct StatefulDeleter
47+
struct DestructG
5848
{
59-
char state;
60-
void operator()(auto* x) const noexcept
49+
~DestructG()
6150
{
51+
++g;
6252
}
6353
};
6454

65-
struct FinalDeleter final
55+
struct CallG
6656
{
6757
void operator()(auto* x) const noexcept
6858
{
59+
++g;
6960
}
7061
};
7162

72-
static_assert(sizeof(Ptr<int, SetsGDeleter>) == sizeof(int*));
73-
74-
// not everyone uses [[no_unique_address]]...
75-
static_assert(!ctl::is_same_v<Ptr<int>, ctl::unique_ptr<int>> ||
76-
sizeof(Ptr<int, FinalDeleter>) == sizeof(int*));
63+
// A unique_ptr with an empty deleter should be the same size as a raw pointer.
64+
static_assert(sizeof(unique_ptr<int, decltype([] {})>) == sizeof(int*));
7765

78-
struct SetsGCtor
66+
struct FinalDeleter final
7967
{
80-
SetsGCtor()
68+
void operator()(auto* x) const noexcept
8169
{
82-
++g;
8370
}
8471
};
8572

86-
struct SetsGDtor
87-
{
88-
~SetsGDtor()
89-
{
90-
++g;
91-
}
92-
};
73+
// ctl::unique_ptr does not need to inherit from its deleter for this property;
74+
// the STL often does, though, so we don't hold them to the following.
75+
static_assert(!ctl::is_same_v<unique_ptr<int>, ctl::unique_ptr<int>> ||
76+
sizeof(unique_ptr<int, FinalDeleter>) == sizeof(int*));
9377

9478
struct Base
9579
{};
@@ -100,36 +84,62 @@ struct Derived : Base
10084
int
10185
main()
10286
{
87+
int a;
10388

10489
{
105-
Ptr<int> x(new int(5));
90+
// Shouldn't cause any memory leaks.
91+
unique_ptr<int> x(new int(5));
10692
}
10793

10894
{
109-
Ptr<int, SetsGDeleter> x(new int());
95+
// Deleter is called if the pointer is non-null when reset.
96+
unique_ptr<int, CallG> x(&a);
11097
x.reset();
11198
if (g != 1)
11299
return 1;
113100
}
114101

115102
{
116103
g = 0;
117-
Ptr<int, SetsGDeleter> x(new int());
118-
delete x.release();
104+
// Deleter is not called if the pointer is null when reset.
105+
unique_ptr<int, CallG> x(&a);
106+
x.release();
119107
x.reset();
120108
if (g)
121109
return 17;
122110
}
123111

124112
{
125-
Ptr<int> x(new int(5)), y(new int(6));
113+
g = 0;
114+
// Deleter is called when the pointer goes out of scope.
115+
{
116+
unique_ptr<int, CallG> x(&a);
117+
}
118+
if (!g)
119+
return 18;
120+
}
121+
122+
{
123+
g = 0;
124+
// Deleter is called if scope ends exceptionally.
125+
try {
126+
unique_ptr<int, CallG> x(&a);
127+
throw 'a';
128+
} catch (char) {
129+
}
130+
if (!g)
131+
return 19;
132+
}
133+
134+
{
135+
unique_ptr<int> x(new int(5)), y(new int(6));
126136
x.swap(y);
127137
if (*x != 6 || *y != 5)
128138
return 2;
129139
}
130140

131141
{
132-
Ptr<int> x;
142+
unique_ptr<int> x;
133143
if (x)
134144
return 3;
135145
x.reset(new int(5));
@@ -139,17 +149,17 @@ main()
139149

140150
{
141151
g = 0;
142-
Ptr<SetsGCtor> x;
152+
unique_ptr<ConstructG> x;
143153
if (g)
144154
return 5;
145-
x = Mk<SetsGCtor>();
155+
x = make_unique<ConstructG>();
146156
if (g != 1)
147157
return 6;
148158
}
149159

150160
{
151161
g = 0;
152-
auto x = Mk<SetsGDtor>();
162+
auto x = make_unique<DestructG>();
153163
if (g)
154164
return 7;
155165
x.reset();
@@ -161,9 +171,9 @@ main()
161171

162172
{
163173
g = 0;
164-
Ptr<SetsGDtor> x, y;
165-
x = Mk<SetsGDtor>();
166-
y = Mk<SetsGDtor>();
174+
unique_ptr<DestructG> x, y;
175+
x = make_unique<DestructG>();
176+
y = make_unique<DestructG>();
167177
#if 0
168178
// shouldn't compile
169179
x = y;
@@ -178,7 +188,7 @@ main()
178188
{
179189
g = 0;
180190
{
181-
auto x = Mk<SetsGDtor>();
191+
auto x = make_unique<DestructG>();
182192
}
183193
if (g != 1)
184194
return 12;
@@ -187,7 +197,7 @@ main()
187197
{
188198
g = 0;
189199
{
190-
auto x = Mk<SetsGDtor>();
200+
auto x = make_unique<DestructG>();
191201
delete x.release();
192202
}
193203
if (g != 1)
@@ -199,13 +209,13 @@ main()
199209
// side effects it has are illegal to detect?
200210
{
201211
g = 0;
202-
auto x = MkRaw<DefaultInitialized>();
212+
auto x = make_unique_for_overwrite<DefaultInitialized>();
203213
if (g)
204214
return 14;
205215
x.reset();
206216
if (g)
207217
return 15;
208-
x = Mk<DefaultInitialized>();
218+
x = make_unique<DefaultInitialized>();
209219
if (g != 1)
210220
return 16;
211221
}
@@ -214,16 +224,15 @@ main()
214224
{
215225
int a;
216226
// Should compile.
217-
Ptr<int, FinalDeleter> x(&a);
218-
Ptr<int, StatefulDeleter> y(&a);
227+
unique_ptr<int, FinalDeleter> x(&a);
219228
}
220229

221230
{
222-
Ptr<Base> x(new Base);
231+
unique_ptr<Base> x(new Base);
223232
x.reset(new Derived);
224233

225-
Ptr<Derived> y(new Derived);
226-
Ptr<Base> z(ctl::move(y));
234+
unique_ptr<Derived> y(new Derived);
235+
unique_ptr<Base> z(ctl::move(y));
227236
}
228237

229238
CheckForMemoryLeaks();

0 commit comments

Comments
 (0)