mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
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.)
This commit is contained in:
parent
389d565d46
commit
48b703b3f6
1 changed files with 77 additions and 68 deletions
|
@ -24,43 +24,44 @@
|
|||
// #include <type_traits>
|
||||
// #define ctl std
|
||||
|
||||
template<typename T, typename D = ctl::default_delete<T>>
|
||||
using Ptr = ctl::unique_ptr<T, D>;
|
||||
using ctl::unique_ptr;
|
||||
using ctl::make_unique;
|
||||
using ctl::make_unique_for_overwrite;
|
||||
|
||||
template<typename T, typename... Args>
|
||||
Ptr<T>
|
||||
Mk(Args&&... args)
|
||||
{
|
||||
return ctl::make_unique<T, Args...>(ctl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Ptr<T>
|
||||
MkRaw()
|
||||
{
|
||||
return ctl::make_unique_for_overwrite<T>();
|
||||
}
|
||||
|
||||
// #undef ctl
|
||||
#undef ctl
|
||||
|
||||
// The following few definitions are used to get observability into aspects of
|
||||
// an object's lifecycle, to make sure that e.g. constructing a unique_ptr of a
|
||||
// type does not construct an object, and that make_unique does construct an
|
||||
// object.
|
||||
static int g = 0;
|
||||
|
||||
struct SetsGDeleter
|
||||
struct ConstructG
|
||||
{
|
||||
ConstructG()
|
||||
{
|
||||
++g;
|
||||
}
|
||||
};
|
||||
|
||||
struct DestructG
|
||||
{
|
||||
~DestructG()
|
||||
{
|
||||
++g;
|
||||
}
|
||||
};
|
||||
|
||||
struct CallG
|
||||
{
|
||||
void operator()(auto* x) const noexcept
|
||||
{
|
||||
++g;
|
||||
delete x;
|
||||
}
|
||||
};
|
||||
|
||||
struct StatefulDeleter
|
||||
{
|
||||
char state;
|
||||
void operator()(auto* x) const noexcept
|
||||
{
|
||||
}
|
||||
};
|
||||
// A unique_ptr with an empty deleter should be the same size as a raw pointer.
|
||||
static_assert(sizeof(unique_ptr<int, decltype([] {})>) == sizeof(int*));
|
||||
|
||||
struct FinalDeleter final
|
||||
{
|
||||
|
@ -69,27 +70,10 @@ struct FinalDeleter final
|
|||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Ptr<int, SetsGDeleter>) == sizeof(int*));
|
||||
|
||||
// not everyone uses [[no_unique_address]]...
|
||||
static_assert(!ctl::is_same_v<Ptr<int>, ctl::unique_ptr<int>> ||
|
||||
sizeof(Ptr<int, FinalDeleter>) == sizeof(int*));
|
||||
|
||||
struct SetsGCtor
|
||||
{
|
||||
SetsGCtor()
|
||||
{
|
||||
++g;
|
||||
}
|
||||
};
|
||||
|
||||
struct SetsGDtor
|
||||
{
|
||||
~SetsGDtor()
|
||||
{
|
||||
++g;
|
||||
}
|
||||
};
|
||||
// ctl::unique_ptr does not need to inherit from its deleter for this property;
|
||||
// the STL often does, though, so we don't hold them to the following.
|
||||
static_assert(!ctl::is_same_v<unique_ptr<int>, ctl::unique_ptr<int>> ||
|
||||
sizeof(unique_ptr<int, FinalDeleter>) == sizeof(int*));
|
||||
|
||||
struct Base
|
||||
{};
|
||||
|
@ -100,13 +84,16 @@ struct Derived : Base
|
|||
int
|
||||
main()
|
||||
{
|
||||
int a;
|
||||
|
||||
{
|
||||
Ptr<int> x(new int(5));
|
||||
// Shouldn't cause any memory leaks.
|
||||
unique_ptr<int> x(new int(5));
|
||||
}
|
||||
|
||||
{
|
||||
Ptr<int, SetsGDeleter> x(new int());
|
||||
// Deleter is called if the pointer is non-null when reset.
|
||||
unique_ptr<int, CallG> x(&a);
|
||||
x.reset();
|
||||
if (g != 1)
|
||||
return 1;
|
||||
|
@ -114,22 +101,45 @@ main()
|
|||
|
||||
{
|
||||
g = 0;
|
||||
Ptr<int, SetsGDeleter> x(new int());
|
||||
delete x.release();
|
||||
// Deleter is not called if the pointer is null when reset.
|
||||
unique_ptr<int, CallG> x(&a);
|
||||
x.release();
|
||||
x.reset();
|
||||
if (g)
|
||||
return 17;
|
||||
}
|
||||
|
||||
{
|
||||
Ptr<int> x(new int(5)), y(new int(6));
|
||||
g = 0;
|
||||
// Deleter is called when the pointer goes out of scope.
|
||||
{
|
||||
unique_ptr<int, CallG> x(&a);
|
||||
}
|
||||
if (!g)
|
||||
return 18;
|
||||
}
|
||||
|
||||
{
|
||||
g = 0;
|
||||
// Deleter is called if scope ends exceptionally.
|
||||
try {
|
||||
unique_ptr<int, CallG> x(&a);
|
||||
throw 'a';
|
||||
} catch (char) {
|
||||
}
|
||||
if (!g)
|
||||
return 19;
|
||||
}
|
||||
|
||||
{
|
||||
unique_ptr<int> x(new int(5)), y(new int(6));
|
||||
x.swap(y);
|
||||
if (*x != 6 || *y != 5)
|
||||
return 2;
|
||||
}
|
||||
|
||||
{
|
||||
Ptr<int> x;
|
||||
unique_ptr<int> x;
|
||||
if (x)
|
||||
return 3;
|
||||
x.reset(new int(5));
|
||||
|
@ -139,17 +149,17 @@ main()
|
|||
|
||||
{
|
||||
g = 0;
|
||||
Ptr<SetsGCtor> x;
|
||||
unique_ptr<ConstructG> x;
|
||||
if (g)
|
||||
return 5;
|
||||
x = Mk<SetsGCtor>();
|
||||
x = make_unique<ConstructG>();
|
||||
if (g != 1)
|
||||
return 6;
|
||||
}
|
||||
|
||||
{
|
||||
g = 0;
|
||||
auto x = Mk<SetsGDtor>();
|
||||
auto x = make_unique<DestructG>();
|
||||
if (g)
|
||||
return 7;
|
||||
x.reset();
|
||||
|
@ -161,9 +171,9 @@ main()
|
|||
|
||||
{
|
||||
g = 0;
|
||||
Ptr<SetsGDtor> x, y;
|
||||
x = Mk<SetsGDtor>();
|
||||
y = Mk<SetsGDtor>();
|
||||
unique_ptr<DestructG> x, y;
|
||||
x = make_unique<DestructG>();
|
||||
y = make_unique<DestructG>();
|
||||
#if 0
|
||||
// shouldn't compile
|
||||
x = y;
|
||||
|
@ -178,7 +188,7 @@ main()
|
|||
{
|
||||
g = 0;
|
||||
{
|
||||
auto x = Mk<SetsGDtor>();
|
||||
auto x = make_unique<DestructG>();
|
||||
}
|
||||
if (g != 1)
|
||||
return 12;
|
||||
|
@ -187,7 +197,7 @@ main()
|
|||
{
|
||||
g = 0;
|
||||
{
|
||||
auto x = Mk<SetsGDtor>();
|
||||
auto x = make_unique<DestructG>();
|
||||
delete x.release();
|
||||
}
|
||||
if (g != 1)
|
||||
|
@ -199,13 +209,13 @@ main()
|
|||
// side effects it has are illegal to detect?
|
||||
{
|
||||
g = 0;
|
||||
auto x = MkRaw<DefaultInitialized>();
|
||||
auto x = make_unique_for_overwrite<DefaultInitialized>();
|
||||
if (g)
|
||||
return 14;
|
||||
x.reset();
|
||||
if (g)
|
||||
return 15;
|
||||
x = Mk<DefaultInitialized>();
|
||||
x = make_unique<DefaultInitialized>();
|
||||
if (g != 1)
|
||||
return 16;
|
||||
}
|
||||
|
@ -214,16 +224,15 @@ main()
|
|||
{
|
||||
int a;
|
||||
// Should compile.
|
||||
Ptr<int, FinalDeleter> x(&a);
|
||||
Ptr<int, StatefulDeleter> y(&a);
|
||||
unique_ptr<int, FinalDeleter> x(&a);
|
||||
}
|
||||
|
||||
{
|
||||
Ptr<Base> x(new Base);
|
||||
unique_ptr<Base> x(new Base);
|
||||
x.reset(new Derived);
|
||||
|
||||
Ptr<Derived> y(new Derived);
|
||||
Ptr<Base> z(ctl::move(y));
|
||||
unique_ptr<Derived> y(new Derived);
|
||||
unique_ptr<Base> z(ctl::move(y));
|
||||
}
|
||||
|
||||
CheckForMemoryLeaks();
|
||||
|
|
Loading…
Reference in a new issue