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>;
|
||||
AA a(f_stor.second());
|
||||
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));
|
||||
return hold.release();
|
||||
}
|
||||
|
@ -739,7 +739,7 @@ Function<R(Args...)>::Function(F f): p_f(nullptr) {
|
|||
using AA = Allocator<FF>;
|
||||
AA a;
|
||||
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));
|
||||
p_f = hold.release();
|
||||
}
|
||||
|
@ -763,7 +763,7 @@ Function<R(Args...)>::Function(AllocatorArg, A const &a, F f):
|
|||
return;
|
||||
}
|
||||
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));
|
||||
p_f = hold.release();
|
||||
}
|
||||
|
|
333
ostd/memory.hh
333
ostd/memory.hh
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <stddef.h>
|
||||
#include <new>
|
||||
#include <memory>
|
||||
|
||||
#include "ostd/utility.hh"
|
||||
#include "ostd/type_traits.hh"
|
||||
|
@ -189,36 +190,6 @@ static T pointer_to(
|
|||
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 {
|
||||
template<typename T>
|
||||
static int ptr_test(...);
|
||||
|
@ -244,308 +215,6 @@ 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 */
|
||||
|
||||
template<typename T>
|
||||
|
|
Loading…
Reference in a new issue