forked from OctaForge/libostd
use unique_ptr
This commit is contained in:
parent
71515c5383
commit
a41299505c
|
@ -551,7 +551,7 @@ public:
|
||||||
using AA = AllocatorRebind<A, FuncCore>;
|
using AA = AllocatorRebind<A, FuncCore>;
|
||||||
AA a(f_stor.second());
|
AA a(f_stor.second());
|
||||||
using D = AllocatorDestructor<AA>;
|
using D = AllocatorDestructor<AA>;
|
||||||
Box<FuncCore, D> hold(a.allocate(1), D(a, 1));
|
std::unique_ptr<FuncCore, D> hold(a.allocate(1), D(a, 1));
|
||||||
::new(hold.get()) FuncCore(f_stor.first(), A(a));
|
::new(hold.get()) FuncCore(f_stor.first(), A(a));
|
||||||
return hold.release();
|
return hold.release();
|
||||||
}
|
}
|
||||||
|
@ -739,7 +739,7 @@ Function<R(Args...)>::Function(F f): p_f(nullptr) {
|
||||||
using AA = Allocator<FF>;
|
using AA = Allocator<FF>;
|
||||||
AA a;
|
AA a;
|
||||||
using D = detail::AllocatorDestructor<AA>;
|
using D = detail::AllocatorDestructor<AA>;
|
||||||
Box<FF, D> hold(a.allocate(1), D(a, 1));
|
std::unique_ptr<FF, D> hold(a.allocate(1), D(a, 1));
|
||||||
::new(hold.get()) FF(std::move(f), Allocator<F>(a));
|
::new(hold.get()) FF(std::move(f), Allocator<F>(a));
|
||||||
p_f = hold.release();
|
p_f = hold.release();
|
||||||
}
|
}
|
||||||
|
@ -763,7 +763,7 @@ Function<R(Args...)>::Function(AllocatorArg, A const &a, F f):
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
using D = detail::AllocatorDestructor<AA>;
|
using D = detail::AllocatorDestructor<AA>;
|
||||||
Box<FF, D> hold(aa.allocate(1), D(aa, 1));
|
std::unique_ptr<FF, D> hold(aa.allocate(1), D(aa, 1));
|
||||||
::new(hold.get()) FF(std::move(f), A(aa));
|
::new(hold.get()) FF(std::move(f), A(aa));
|
||||||
p_f = hold.release();
|
p_f = hold.release();
|
||||||
}
|
}
|
||||||
|
|
333
ostd/memory.hh
333
ostd/memory.hh
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "ostd/utility.hh"
|
#include "ostd/utility.hh"
|
||||||
#include "ostd/type_traits.hh"
|
#include "ostd/type_traits.hh"
|
||||||
|
@ -189,36 +190,6 @@ static T pointer_to(
|
||||||
return detail::PointerTo<T>::pointer_to(r);
|
return detail::PointerTo<T>::pointer_to(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* default deleter */
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct DefaultDelete {
|
|
||||||
constexpr DefaultDelete() = default;
|
|
||||||
|
|
||||||
template<typename U>
|
|
||||||
DefaultDelete(DefaultDelete<U> const &) noexcept {};
|
|
||||||
|
|
||||||
void operator()(T *p) const {
|
|
||||||
delete p;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct DefaultDelete<T[]> {
|
|
||||||
constexpr DefaultDelete() = default;
|
|
||||||
|
|
||||||
template<typename U>
|
|
||||||
DefaultDelete(DefaultDelete<U[]> const &) noexcept {};
|
|
||||||
|
|
||||||
void operator()(T *p) const {
|
|
||||||
delete[] p;
|
|
||||||
}
|
|
||||||
template<typename U>
|
|
||||||
void operator()(U *) const = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* box */
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static int ptr_test(...);
|
static int ptr_test(...);
|
||||||
|
@ -244,308 +215,6 @@ namespace detail {
|
||||||
};
|
};
|
||||||
} /* namespace detail */
|
} /* namespace detail */
|
||||||
|
|
||||||
template<typename T, typename D = DefaultDelete<T>>
|
|
||||||
struct Box {
|
|
||||||
using Element = T;
|
|
||||||
using Deleter = D;
|
|
||||||
using Pointer = typename detail::PointerType<T, D>::Type;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Nat { int x; };
|
|
||||||
|
|
||||||
using Dref = RemoveReference<D> &;
|
|
||||||
using Dcref = RemoveReference<D> const &;
|
|
||||||
|
|
||||||
public:
|
|
||||||
constexpr Box() noexcept: p_stor(nullptr, D()) {
|
|
||||||
static_assert(!IsPointer<D>, "Box constructed with null fptr deleter");
|
|
||||||
}
|
|
||||||
constexpr Box(Nullptr) noexcept: p_stor(nullptr, D()) {
|
|
||||||
static_assert(!IsPointer<D>, "Box constructed with null fptr deleter");
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit Box(Pointer p) noexcept: p_stor(p, D()) {
|
|
||||||
static_assert(!IsPointer<D>, "Box constructed with null fptr deleter");
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(
|
|
||||||
Pointer p, Conditional<IsReference<D>, D, AddLvalueReference<D const>> d
|
|
||||||
) noexcept:
|
|
||||||
p_stor(p, d)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Box(Pointer p, RemoveReference<D> &&d) noexcept:
|
|
||||||
p_stor(p, std::move(d))
|
|
||||||
{
|
|
||||||
static_assert(!IsReference<D>, "rvalue deleter cannot be a ref");
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(Box &&u) noexcept:
|
|
||||||
p_stor(u.release(), std::forward<D>(u.get_deleter()))
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename TT, typename DD>
|
|
||||||
Box(
|
|
||||||
Box<TT, DD> &&u, EnableIf<
|
|
||||||
!IsArray<TT> &&
|
|
||||||
IsConvertible<typename Box<TT, DD>::Pointer, Pointer> &&
|
|
||||||
IsConvertible<DD, D> && (!IsReference<D> || IsSame<D, DD>),
|
|
||||||
Nat
|
|
||||||
> = Nat()
|
|
||||||
) noexcept: p_stor(u.release(), std::forward<DD>(u.get_deleter())) {}
|
|
||||||
|
|
||||||
Box &operator=(Box &&u) noexcept {
|
|
||||||
reset(u.release());
|
|
||||||
p_stor.second() = std::forward<D>(u.get_deleter());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TT, typename DD>
|
|
||||||
EnableIf<
|
|
||||||
!IsArray<TT> &&
|
|
||||||
IsConvertible<typename Box<TT, DD>::Pointer, Pointer> &&
|
|
||||||
IsAssignable<D &, DD &&>,
|
|
||||||
Box &
|
|
||||||
> operator=(Box<TT, DD> &&u) noexcept {
|
|
||||||
reset(u.release());
|
|
||||||
p_stor.second() = std::forward<DD>(u.get_deleter());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Box &operator=(Nullptr) noexcept {
|
|
||||||
reset();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Box() { reset(); }
|
|
||||||
|
|
||||||
AddLvalueReference<T> operator*() const { return *p_stor.first(); }
|
|
||||||
Pointer operator->() const noexcept { return p_stor.first(); }
|
|
||||||
|
|
||||||
explicit operator bool() const noexcept {
|
|
||||||
return p_stor.first() != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Pointer get() const noexcept { return p_stor.first(); }
|
|
||||||
|
|
||||||
Dref get_deleter() noexcept { return p_stor.second(); }
|
|
||||||
Dcref get_deleter() const noexcept { return p_stor.second(); }
|
|
||||||
|
|
||||||
Pointer release() noexcept {
|
|
||||||
Pointer p = p_stor.first();
|
|
||||||
p_stor.first() = nullptr;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset(Pointer p = nullptr) noexcept {
|
|
||||||
Pointer tmp = p_stor.first();
|
|
||||||
p_stor.first() = p;
|
|
||||||
if (tmp) {
|
|
||||||
p_stor.second()(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap(Box &u) noexcept {
|
|
||||||
p_stor.swap(u.p_stor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
detail::CompressedPair<T *, D> p_stor;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template<typename T, typename U, bool = IsSame<
|
|
||||||
RemoveCv<PointerElement<T>>,
|
|
||||||
RemoveCv<PointerElement<U>>
|
|
||||||
>>
|
|
||||||
constexpr bool SameOrLessCvQualifiedBase = IsConvertible<T, U>;
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
constexpr bool SameOrLessCvQualifiedBase<T, U, false> = false;
|
|
||||||
|
|
||||||
template<typename T, typename U, bool =
|
|
||||||
IsPointer<T> || IsSame<T, U> || detail::HasElement<T>::value
|
|
||||||
>
|
|
||||||
constexpr bool SameOrLessCvQualified = SameOrLessCvQualifiedBase<T, U>;
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
constexpr bool SameOrLessCvQualified<T, U, false> = false;
|
|
||||||
} /* namespace detail */
|
|
||||||
|
|
||||||
template<typename T, typename D>
|
|
||||||
struct Box<T[], D> {
|
|
||||||
using Element = T;
|
|
||||||
using Deleter = D;
|
|
||||||
using Pointer = typename detail::PointerType<T, D>::Type;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct Nat { int x; };
|
|
||||||
|
|
||||||
using Dref = RemoveReference<D> &;
|
|
||||||
using Dcref = RemoveReference<D> const &;
|
|
||||||
|
|
||||||
public:
|
|
||||||
constexpr Box() noexcept: p_stor(nullptr, D()) {
|
|
||||||
static_assert(!IsPointer<D>, "Box constructed with null fptr deleter");
|
|
||||||
}
|
|
||||||
constexpr Box(Nullptr) noexcept: p_stor(nullptr, D()) {
|
|
||||||
static_assert(!IsPointer<D>, "Box constructed with null fptr deleter");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U> explicit Box(U p, EnableIf<
|
|
||||||
detail::SameOrLessCvQualified<U, Pointer>, Nat
|
|
||||||
> = Nat()) noexcept: p_stor(p, D()) {
|
|
||||||
static_assert(!IsPointer<D>, "Box constructed with null fptr deleter");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U> Box(U p, Conditional<
|
|
||||||
IsReference<D>, D, AddLvalueReference<D const>
|
|
||||||
> d, EnableIf<
|
|
||||||
detail::SameOrLessCvQualified<U, Pointer>, Nat
|
|
||||||
> = Nat()) noexcept:
|
|
||||||
p_stor(p, d)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Box(
|
|
||||||
Nullptr, Conditional<IsReference<D>, D, AddLvalueReference<D const>> d
|
|
||||||
) noexcept:
|
|
||||||
p_stor(nullptr, d)
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename U> Box(U p, RemoveReference<D> &&d,
|
|
||||||
EnableIf<detail::SameOrLessCvQualified<U, Pointer>, Nat> = Nat()) noexcept:
|
|
||||||
p_stor(p, std::move(d))
|
|
||||||
{
|
|
||||||
static_assert(!IsReference<D>, "rvalue deleter cannot be a ref");
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(Nullptr, RemoveReference<D> &&d) noexcept:
|
|
||||||
p_stor(nullptr, std::move(d))
|
|
||||||
{
|
|
||||||
static_assert(!IsReference<D>, "rvalue deleter cannot be a ref");
|
|
||||||
}
|
|
||||||
|
|
||||||
Box(Box &&u) noexcept:
|
|
||||||
p_stor(u.release(), std::forward<D>(u.get_deleter()))
|
|
||||||
{}
|
|
||||||
|
|
||||||
template<typename TT, typename DD>
|
|
||||||
Box(
|
|
||||||
Box<TT, DD> &&u, EnableIf<
|
|
||||||
IsArray<TT> &&
|
|
||||||
detail::SameOrLessCvQualified<typename Box<TT, DD>::Pointer,Pointer> &&
|
|
||||||
IsConvertible<DD, D> && (!IsReference<D> || IsSame<D, DD>),
|
|
||||||
Nat
|
|
||||||
> = Nat()
|
|
||||||
) noexcept:
|
|
||||||
p_stor(u.release(), std::forward<DD>(u.get_deleter()))
|
|
||||||
{}
|
|
||||||
|
|
||||||
Box &operator=(Box &&u) noexcept {
|
|
||||||
reset(u.release());
|
|
||||||
p_stor.second() = std::forward<D>(u.get_deleter());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TT, typename DD>
|
|
||||||
EnableIf<
|
|
||||||
IsArray<TT> &&
|
|
||||||
detail::SameOrLessCvQualified<typename Box<TT, DD>::Pointer, Pointer> &&
|
|
||||||
IsAssignable<D &, DD &&>,
|
|
||||||
Box &
|
|
||||||
> operator=(Box<TT, DD> &&u) noexcept {
|
|
||||||
reset(u.release());
|
|
||||||
p_stor.second() = std::forward<DD>(u.get_deleter());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Box &operator=(Nullptr) noexcept {
|
|
||||||
reset();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Box() { reset(); }
|
|
||||||
|
|
||||||
AddLvalueReference<T> operator[](Size idx) const {
|
|
||||||
return p_stor.first()[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const noexcept {
|
|
||||||
return p_stor.first() != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Pointer get() const noexcept { return p_stor.first(); }
|
|
||||||
|
|
||||||
Dref get_deleter() noexcept { return p_stor.second(); }
|
|
||||||
Dcref get_deleter() const noexcept { return p_stor.second(); }
|
|
||||||
|
|
||||||
Pointer release() noexcept {
|
|
||||||
Pointer p = p_stor.first();
|
|
||||||
p_stor.first() = nullptr;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename U>
|
|
||||||
EnableIf<
|
|
||||||
detail::SameOrLessCvQualified<U, Pointer>, void
|
|
||||||
> reset(U p) noexcept {
|
|
||||||
Pointer tmp = p_stor.first();
|
|
||||||
p_stor.first() = p;
|
|
||||||
if (tmp) {
|
|
||||||
p_stor.second()(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset(Nullptr) noexcept {
|
|
||||||
Pointer tmp = p_stor.first();
|
|
||||||
p_stor.first() = nullptr;
|
|
||||||
if (tmp) {
|
|
||||||
p_stor.second()(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset() noexcept {
|
|
||||||
reset(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void swap(Box &u) noexcept {
|
|
||||||
p_stor.swap(u.p_stor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
detail::CompressedPair<T *, D> p_stor;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template<typename T>
|
|
||||||
struct BoxIf {
|
|
||||||
using BoxType = Box<T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct BoxIf<T[]> {
|
|
||||||
using BoxUnknownSize = Box<T[]>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, Size N>
|
|
||||||
struct BoxIf<T[N]> {
|
|
||||||
using BoxKnownSize = void;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename ...A>
|
|
||||||
typename detail::BoxIf<T>::BoxType make_box(A &&...args) {
|
|
||||||
return Box<T>(new T(std::forward<A>(args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
typename detail::BoxIf<T>::BoxUnknownSize make_box(Size n) {
|
|
||||||
return Box<T>(new RemoveExtent<T>[n]());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename ...A>
|
|
||||||
typename detail::BoxIf<T>::BoxKnownSize make_box(A &&...args) = delete;
|
|
||||||
|
|
||||||
/* allocator */
|
/* allocator */
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
Loading…
Reference in a new issue