2024-06-16 02:54:52 +00:00
|
|
|
// -*-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
|
2024-06-29 02:07:35 +00:00
|
|
|
#ifndef CTL_UNIQUE_PTR_H_
|
|
|
|
#define CTL_UNIQUE_PTR_H_
|
|
|
|
#include "add_lvalue_reference.h"
|
|
|
|
#include "default_delete.h"
|
|
|
|
#include "is_convertible.h"
|
|
|
|
#include "is_reference.h"
|
|
|
|
#include "is_same.h"
|
2024-06-19 05:00:59 +00:00
|
|
|
#include "utility.h"
|
2024-06-16 02:54:52 +00:00
|
|
|
|
|
|
|
namespace ctl {
|
|
|
|
|
2024-06-29 02:07:35 +00:00
|
|
|
template<typename T, typename D = ctl::default_delete<T>>
|
2024-06-16 02:54:52 +00:00
|
|
|
struct unique_ptr
|
|
|
|
{
|
|
|
|
using pointer = T*;
|
|
|
|
using element_type = T;
|
|
|
|
using deleter_type = D;
|
|
|
|
|
|
|
|
pointer p;
|
|
|
|
[[no_unique_address]] deleter_type d;
|
|
|
|
|
2024-06-20 22:44:31 +00:00
|
|
|
constexpr unique_ptr(const nullptr_t = nullptr) noexcept : p(nullptr), d()
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2024-06-29 02:07:35 +00:00
|
|
|
constexpr explicit unique_ptr(pointer p) noexcept : p(p), d()
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2024-06-29 02:07:35 +00:00
|
|
|
constexpr unique_ptr(pointer p, const D& d) noexcept : p(p), d(d)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
constexpr unique_ptr(pointer p, D&& d) noexcept : p(p), d(ctl::move(d))
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2024-06-20 22:44:31 +00:00
|
|
|
template<typename U, typename E>
|
|
|
|
constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept
|
2024-06-29 02:07:35 +00:00
|
|
|
: p(u.release()), d(ctl::forward<E>(u.get_deleter()))
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
2024-06-29 02:07:35 +00:00
|
|
|
static_assert(ctl::is_convertible<typename unique_ptr<U, E>::pointer,
|
|
|
|
pointer>::value,
|
|
|
|
"U* must be implicitly convertible to T*");
|
|
|
|
static_assert(
|
|
|
|
(ctl::is_reference<D>::value && ctl::is_same<D, E>::value) ||
|
|
|
|
(!ctl::is_reference<D>::value && ctl::is_convertible<E, D>::value),
|
|
|
|
"The deleter must be convertible to the target deleter type");
|
2024-06-16 02:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unique_ptr(const unique_ptr&) = delete;
|
|
|
|
|
2024-06-29 02:07:35 +00:00
|
|
|
constexpr ~unique_ptr() noexcept
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
2024-06-20 22:44:31 +00:00
|
|
|
if (p)
|
|
|
|
d(p);
|
2024-06-16 02:54:52 +00:00
|
|
|
}
|
|
|
|
|
2024-06-20 22:44:31 +00:00
|
|
|
constexpr unique_ptr& operator=(unique_ptr r) noexcept
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
|
|
|
swap(r);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2024-06-29 02:07:35 +00:00
|
|
|
template<typename U, typename E>
|
|
|
|
constexpr unique_ptr& operator=(unique_ptr<U, E>&& r) noexcept
|
|
|
|
{
|
|
|
|
reset(r.release());
|
|
|
|
d = ctl::forward<E>(r.get_deleter());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
constexpr unique_ptr& operator=(nullptr_t) noexcept
|
|
|
|
{
|
|
|
|
reset();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2024-06-20 22:44:31 +00:00
|
|
|
constexpr pointer release() noexcept
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
|
|
|
pointer r = p;
|
|
|
|
p = nullptr;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2024-06-29 02:07:35 +00:00
|
|
|
constexpr void reset(pointer p2 = pointer()) noexcept
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
2024-06-29 02:07:35 +00:00
|
|
|
pointer old = p;
|
2024-06-20 22:44:31 +00:00
|
|
|
p = p2;
|
2024-06-29 02:07:35 +00:00
|
|
|
if (old)
|
|
|
|
d(old);
|
2024-06-16 02:54:52 +00:00
|
|
|
}
|
|
|
|
|
2024-06-20 22:44:31 +00:00
|
|
|
constexpr void swap(unique_ptr& r) noexcept
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
2024-06-19 05:00:59 +00:00
|
|
|
using ctl::swap;
|
2024-06-16 02:54:52 +00:00
|
|
|
swap(p, r.p);
|
|
|
|
swap(d, r.d);
|
|
|
|
}
|
|
|
|
|
2024-06-20 22:44:31 +00:00
|
|
|
constexpr pointer get() const noexcept
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2024-06-20 22:44:31 +00:00
|
|
|
constexpr deleter_type& get_deleter() noexcept
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2024-06-20 22:44:31 +00:00
|
|
|
constexpr const deleter_type& get_deleter() const noexcept
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2024-06-20 22:44:31 +00:00
|
|
|
constexpr explicit operator bool() const noexcept
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
2024-06-29 02:07:35 +00:00
|
|
|
return p != nullptr;
|
2024-06-16 02:54:52 +00:00
|
|
|
}
|
|
|
|
|
2024-06-29 02:07:35 +00:00
|
|
|
constexpr typename ctl::add_lvalue_reference<T>::type operator*() const
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
|
|
|
return *p;
|
|
|
|
}
|
|
|
|
|
2024-06-29 02:07:35 +00:00
|
|
|
constexpr pointer operator->() const noexcept
|
2024-06-16 02:54:52 +00:00
|
|
|
{
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename... Args>
|
2024-06-20 22:44:31 +00:00
|
|
|
constexpr unique_ptr<T>
|
2024-06-16 02:54:52 +00:00
|
|
|
make_unique(Args&&... args)
|
|
|
|
{
|
2024-06-19 05:00:59 +00:00
|
|
|
return unique_ptr<T>(new T(ctl::forward<Args>(args)...));
|
2024-06-16 02:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2024-06-20 22:44:31 +00:00
|
|
|
constexpr unique_ptr<T>
|
2024-06-16 02:54:52 +00:00
|
|
|
make_unique_for_overwrite()
|
|
|
|
{
|
|
|
|
return unique_ptr<T>(new T);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace ctl
|
2024-06-29 02:07:35 +00:00
|
|
|
|
|
|
|
#endif // CTL_UNIQUE_PTR_H_
|