mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-05 09:20:29 +00:00
Minor unique_ptr cleanup
Explicitly value-initializes the deleter, even though I have not found a way to get the deleter to act like it’s been default-initialized in unit tests so far. Uses auto in reset. The static cast is apparently not needed (unless I’m missing some case I didn’t think of.) Tests Base/Derived reset. Implements the general move constructor - turns out that the reason this didn’t work before was that default_delete<U> was not move constructible from default_delete<T>. Drop inline specifiers from functions defined entirely inside the struct definition since they are implicitly inline. Adds some constexpr declarations to default_delete. Adds default_delete specialization for T[]. Makes parameters const.
This commit is contained in:
parent
a795017416
commit
929fb1ad5d
2 changed files with 57 additions and 28 deletions
|
@ -2,6 +2,7 @@
|
||||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||||
#ifndef COSMOPOLITAN_CTL_UNIQUE_PTR_H_
|
#ifndef COSMOPOLITAN_CTL_UNIQUE_PTR_H_
|
||||||
#define COSMOPOLITAN_CTL_UNIQUE_PTR_H_
|
#define COSMOPOLITAN_CTL_UNIQUE_PTR_H_
|
||||||
|
#include <__type_traits/is_convertible.h>
|
||||||
#include <__utility/forward.h>
|
#include <__utility/forward.h>
|
||||||
#include <__utility/move.h>
|
#include <__utility/move.h>
|
||||||
#include <__utility/swap.h>
|
#include <__utility/swap.h>
|
||||||
|
@ -11,12 +12,31 @@ namespace ctl {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct default_delete
|
struct default_delete
|
||||||
{
|
{
|
||||||
constexpr void operator()(T* p) const noexcept
|
constexpr default_delete() noexcept = default;
|
||||||
|
template<typename U>
|
||||||
|
constexpr default_delete(default_delete<U>&&) noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
constexpr void operator()(T* const p) const noexcept
|
||||||
{
|
{
|
||||||
delete p;
|
delete p;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct default_delete<T[]>
|
||||||
|
{
|
||||||
|
constexpr default_delete() noexcept = default;
|
||||||
|
template<typename U>
|
||||||
|
constexpr default_delete(default_delete<U>&&) noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
constexpr void operator()(T* const p) const noexcept
|
||||||
|
{
|
||||||
|
delete[] p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T, typename D = default_delete<T>>
|
template<typename T, typename D = default_delete<T>>
|
||||||
struct unique_ptr
|
struct unique_ptr
|
||||||
{
|
{
|
||||||
|
@ -27,102 +47,97 @@ struct unique_ptr
|
||||||
pointer p;
|
pointer p;
|
||||||
[[no_unique_address]] deleter_type d;
|
[[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(auto* const p, auto&& d) noexcept
|
||||||
: p(p), d(std::forward<decltype(d)>(d))
|
: p(p), d(std::forward<decltype(d)>(d))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr unique_ptr(unique_ptr&& u) noexcept : p(u.p), d(std::move(u.d))
|
template<typename U, typename E>
|
||||||
|
requires std::is_convertible_v<U, T> && std::is_convertible_v<E, D>
|
||||||
|
constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept
|
||||||
|
: p(u.p), d(std::move(u.d))
|
||||||
{
|
{
|
||||||
u.p = nullptr;
|
u.p = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mrdomino):
|
|
||||||
// template <typename U, typename E>
|
|
||||||
// unique_ptr(unique_ptr<U, E>&& u) noexcept;
|
|
||||||
|
|
||||||
unique_ptr(const unique_ptr&) = delete;
|
unique_ptr(const unique_ptr&) = delete;
|
||||||
|
|
||||||
inline ~unique_ptr() /* noexcept */
|
~unique_ptr() /* noexcept */
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unique_ptr& operator=(unique_ptr r) noexcept
|
unique_ptr& operator=(unique_ptr r) noexcept
|
||||||
{
|
{
|
||||||
swap(r);
|
swap(r);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline pointer release() noexcept
|
pointer release() noexcept
|
||||||
{
|
{
|
||||||
pointer r = p;
|
pointer r = p;
|
||||||
p = nullptr;
|
p = nullptr;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reset(nullptr_t = nullptr) noexcept
|
void reset(const nullptr_t = nullptr) noexcept
|
||||||
{
|
{
|
||||||
if (p)
|
if (p)
|
||||||
d(p);
|
d(p);
|
||||||
p = nullptr;
|
p = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename U>
|
void reset(auto* const p2)
|
||||||
// TODO(mrdomino):
|
|
||||||
/* requires is_convertible_v<U, T> */
|
|
||||||
inline void reset(U* p2)
|
|
||||||
{
|
{
|
||||||
if (p) {
|
if (p) {
|
||||||
d(p);
|
d(p);
|
||||||
}
|
}
|
||||||
p = static_cast<pointer>(p2);
|
p = p2;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void swap(unique_ptr& r) noexcept
|
void swap(unique_ptr& r) noexcept
|
||||||
{
|
{
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(p, r.p);
|
swap(p, r.p);
|
||||||
swap(d, r.d);
|
swap(d, r.d);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline pointer get() const noexcept
|
pointer get() const noexcept
|
||||||
{
|
{
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline deleter_type& get_deleter() noexcept
|
deleter_type& get_deleter() noexcept
|
||||||
{
|
{
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const deleter_type& get_deleter() const noexcept
|
const deleter_type& get_deleter() const noexcept
|
||||||
{
|
{
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline explicit operator bool() const noexcept
|
explicit operator bool() const noexcept
|
||||||
{
|
{
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline element_type& operator*() const
|
element_type& operator*() const noexcept(noexcept(*std::declval<pointer>()))
|
||||||
noexcept(noexcept(*std::declval<pointer>()))
|
|
||||||
{
|
{
|
||||||
if (!p)
|
if (!p)
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
return *p;
|
return *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline pointer operator->() const noexcept
|
pointer operator->() const noexcept
|
||||||
{
|
{
|
||||||
if (!p)
|
if (!p)
|
||||||
__builtin_trap();
|
__builtin_trap();
|
||||||
|
@ -131,14 +146,14 @@ struct unique_ptr
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
inline unique_ptr<T>
|
unique_ptr<T>
|
||||||
make_unique(Args&&... args)
|
make_unique(Args&&... args)
|
||||||
{
|
{
|
||||||
return unique_ptr<T>(new T(std::forward<Args>(args)...));
|
return unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline unique_ptr<T>
|
unique_ptr<T>
|
||||||
make_unique_for_overwrite()
|
make_unique_for_overwrite()
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -91,6 +91,12 @@ struct SetsGDtor
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Base
|
||||||
|
{};
|
||||||
|
|
||||||
|
struct Derived : Base
|
||||||
|
{};
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
@ -211,6 +217,14 @@ main()
|
||||||
Ptr<int, StatefulDeleter> y(&a);
|
Ptr<int, StatefulDeleter> y(&a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Ptr<Base> x(new Base);
|
||||||
|
x.reset(new Derived);
|
||||||
|
|
||||||
|
Ptr<Derived> y(new Derived);
|
||||||
|
Ptr<Base> z(std::move(y));
|
||||||
|
}
|
||||||
|
|
||||||
// next is 18
|
// next is 18
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue