// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*- // vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi #ifndef COSMOPOLITAN_CTL_UNIQUE_PTR_H_ #define COSMOPOLITAN_CTL_UNIQUE_PTR_H_ #include "utility.h" namespace ctl { template struct default_delete { constexpr void operator()(T* p) const noexcept { delete p; } }; template> struct unique_ptr { using pointer = T*; using element_type = T; using deleter_type = D; pointer p; [[no_unique_address]] deleter_type d; constexpr unique_ptr(nullptr_t = nullptr) noexcept : p(nullptr) { } constexpr unique_ptr(pointer p) noexcept : p(p) { } constexpr unique_ptr(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)) { u.p = nullptr; } // TODO(mrdomino): // template // unique_ptr(unique_ptr&& u) noexcept; unique_ptr(const unique_ptr&) = delete; inline ~unique_ptr() /* noexcept */ { reset(); } inline unique_ptr& operator=(unique_ptr r) noexcept { swap(r); return *this; } inline pointer release() noexcept { pointer r = p; p = nullptr; return r; } inline void reset(nullptr_t = nullptr) noexcept { if (p) d(p); p = nullptr; } 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 { using ctl::swap; swap(p, r.p); swap(d, r.d); } inline pointer get() const noexcept { return p; } inline deleter_type& get_deleter() noexcept { return d; } inline const deleter_type& get_deleter() const noexcept { return d; } inline explicit operator bool() const noexcept { return p; } inline element_type& operator*() const noexcept(noexcept(*ctl::declval())) { if (!p) __builtin_trap(); return *p; } inline pointer operator->() const noexcept { if (!p) __builtin_trap(); return p; } }; template inline unique_ptr make_unique(Args&&... args) { return unique_ptr(new T(ctl::forward(args)...)); } template inline unique_ptr make_unique_for_overwrite() { #if 0 // You'd think that it'd work like this, but std::unique_ptr does not. return unique_ptr( static_cast(::operator new(sizeof(T), align_val_t(alignof(T))))); #else return unique_ptr(new T); #endif } // TODO(mrdomino): specializations for T[] } // namespace ctl #endif // COSMOPOLITAN_CTL_UNIQUE_PTR_H_