diff --git a/ctl/unique_ptr.h b/ctl/unique_ptr.h index 6217e2de5..c2ebae7ba 100644 --- a/ctl/unique_ptr.h +++ b/ctl/unique_ptr.h @@ -3,18 +3,38 @@ #ifndef COSMOPOLITAN_CTL_UNIQUE_PTR_H_ #define COSMOPOLITAN_CTL_UNIQUE_PTR_H_ #include "utility.h" +#include <__type_traits/is_convertible.h> namespace ctl { template struct default_delete { - constexpr void operator()(T* p) const noexcept + constexpr default_delete() noexcept = default; + template + constexpr default_delete(default_delete&&) noexcept + { + } + constexpr void operator()(T* const p) const noexcept { delete p; } }; +template +struct default_delete +{ + constexpr default_delete() noexcept = default; + template + constexpr default_delete(default_delete&&) noexcept + { + } + constexpr void operator()(T* const p) const noexcept + { + delete[] p; + } +}; + template> struct unique_ptr { @@ -25,102 +45,91 @@ struct unique_ptr pointer p; [[no_unique_address]] deleter_type d; - constexpr unique_ptr(nullptr_t = nullptr) noexcept : p(nullptr) + constexpr unique_ptr(const nullptr_t = nullptr) noexcept : p(nullptr), d() { } - constexpr unique_ptr(pointer p) noexcept : p(p) + constexpr unique_ptr(const pointer p) noexcept : p(p), d() { } - constexpr unique_ptr(pointer p, auto&& d) noexcept + constexpr unique_ptr(const pointer p, auto&& d) noexcept : p(p), d(ctl::forward(d)) { } - constexpr unique_ptr(unique_ptr&& u) noexcept : p(u.p), d(ctl::move(u.d)) + template + requires std::is_convertible_v && std::is_convertible_v + constexpr unique_ptr(unique_ptr&& u) noexcept + : p(u.p), d(ctl::move(u.d)) { u.p = nullptr; } - // TODO(mrdomino): - // template - // unique_ptr(unique_ptr&& u) noexcept; - unique_ptr(const unique_ptr&) = delete; - inline ~unique_ptr() /* noexcept */ + constexpr ~unique_ptr() /* noexcept */ { - reset(); + if (p) + d(p); } - inline unique_ptr& operator=(unique_ptr r) noexcept + constexpr unique_ptr& operator=(unique_ptr r) noexcept { swap(r); return *this; } - inline pointer release() noexcept + constexpr pointer release() noexcept { pointer r = p; p = nullptr; return r; } - inline void reset(nullptr_t = nullptr) noexcept + constexpr void reset(const pointer p2 = pointer()) noexcept { - if (p) - d(p); - p = nullptr; + const pointer r = p; + p = p2; + if (r) + d(r); } - template - // TODO(mrdomino): - /* requires is_convertible_v */ - inline void reset(U* p2) - { - if (p) { - d(p); - } - p = static_cast(p2); - } - - inline void swap(unique_ptr& r) noexcept + constexpr void swap(unique_ptr& r) noexcept { using ctl::swap; swap(p, r.p); swap(d, r.d); } - inline pointer get() const noexcept + constexpr pointer get() const noexcept { return p; } - inline deleter_type& get_deleter() noexcept + constexpr deleter_type& get_deleter() noexcept { return d; } - inline const deleter_type& get_deleter() const noexcept + constexpr const deleter_type& get_deleter() const noexcept { return d; } - inline explicit operator bool() const noexcept + constexpr explicit operator bool() const noexcept { return p; } - inline element_type& operator*() const - noexcept(noexcept(*ctl::declval())) + element_type& operator*() const noexcept(noexcept(*ctl::declval())) { if (!p) __builtin_trap(); return *p; } - inline pointer operator->() const noexcept + pointer operator->() const noexcept { if (!p) __builtin_trap(); @@ -129,14 +138,14 @@ struct unique_ptr }; template -inline unique_ptr +constexpr unique_ptr make_unique(Args&&... args) { return unique_ptr(new T(ctl::forward(args)...)); } template -inline unique_ptr +constexpr unique_ptr make_unique_for_overwrite() { #if 0 diff --git a/test/ctl/unique_ptr_test.cc b/test/ctl/unique_ptr_test.cc index 77e4b1573..83f63e6e8 100644 --- a/test/ctl/unique_ptr_test.cc +++ b/test/ctl/unique_ptr_test.cc @@ -91,6 +91,12 @@ struct SetsGDtor } }; +struct Base +{}; + +struct Derived : Base +{}; + int main() { @@ -211,7 +217,16 @@ main() Ptr y(&a); } + { + Ptr x(new Base); + x.reset(new Derived); + + Ptr y(new Derived); + Ptr z(ctl::move(y)); + } + // next is 18 + CheckForMemoryLeaks(); return 0; }