2015-04-18 18:02:44 +00:00
|
|
|
/* Memory utilities for OctaSTD.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef OCTA_MEMORY_H
|
|
|
|
#define OCTA_MEMORY_H
|
|
|
|
|
2015-04-27 17:56:17 +00:00
|
|
|
#include "octa/new.h"
|
|
|
|
#include "octa/type_traits.h"
|
|
|
|
|
2015-04-18 18:02:44 +00:00
|
|
|
namespace octa {
|
2015-04-27 17:56:17 +00:00
|
|
|
/* address of */
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
template<typename T> constexpr T *address_of(T &v) noexcept {
|
2015-04-18 18:02:44 +00:00
|
|
|
return reinterpret_cast<T *>(&const_cast<char &>
|
|
|
|
(reinterpret_cast<const volatile char &>(v)));
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
/* pointer traits */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaHasElementType {
|
|
|
|
template<typename U>
|
|
|
|
static int __octa_test(...);
|
|
|
|
template<typename U>
|
2015-04-27 18:38:34 +00:00
|
|
|
static char __octa_test(typename U::element_type * = 0);
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
static constexpr bool value = (sizeof(__octa_test<T>(0)) == 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, bool = __OctaHasElementType<T>::value>
|
|
|
|
struct __OctaPtrTraitsElementType;
|
|
|
|
|
|
|
|
template<typename T> struct __OctaPtrTraitsElementType<T, true> {
|
2015-04-27 18:38:34 +00:00
|
|
|
typedef typename T::element_type type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<template<typename, typename...> class T, typename U, typename ...A>
|
|
|
|
struct __OctaPtrTraitsElementType<T<U, A...>, true> {
|
2015-04-27 18:38:34 +00:00
|
|
|
typedef typename T<U, A...>::element_type type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<template<typename, typename...> class T, typename U, typename ...A>
|
|
|
|
struct __OctaPtrTraitsElementType<T<U, A...>, false> {
|
|
|
|
typedef U type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct __OctaHasDifferenceType {
|
|
|
|
template<typename U>
|
|
|
|
static int __octa_test(...);
|
|
|
|
template<typename U>
|
2015-04-27 18:38:34 +00:00
|
|
|
static char __octa_test(typename U::difference_type * = 0);
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
static constexpr bool value = (sizeof(__octa_test<T>(0)) == 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, bool = __OctaHasDifferenceType<T>::value>
|
|
|
|
struct __OctaPtrTraitsDifferenceType {
|
|
|
|
typedef ptrdiff_t type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T> struct __OctaPtrTraitsDifferenceType<T, true> {
|
2015-04-27 18:38:34 +00:00
|
|
|
typedef typename T::difference_type type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
struct __OctaHasRebind {
|
|
|
|
template<typename V>
|
|
|
|
static int __octa_test(...);
|
|
|
|
template<typename V>
|
2015-04-27 18:38:34 +00:00
|
|
|
static char __octa_test(typename V::template rebind<U> * = 0);
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
static constexpr bool value = (sizeof(__octa_test<T>(0)) == 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename U, bool = __OctaHasRebind<T, U>::value>
|
|
|
|
struct __OctaPtrTraitsRebind {
|
|
|
|
typedef typename T::template rebind<U> type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<template<typename, typename...> class T, typename U,
|
|
|
|
typename ...A, typename V
|
|
|
|
>
|
|
|
|
struct __OctaPtrTraitsRebind<T<U, A...>, V, true> {
|
2015-04-27 18:38:34 +00:00
|
|
|
typedef typename T<U, A...>::template rebind<V> type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<template<typename, typename...> class T, typename U,
|
|
|
|
typename ...A, typename V
|
|
|
|
>
|
|
|
|
struct __OctaPtrTraitsRebind<T<U, A...>, V, false> {
|
|
|
|
typedef T<V, A...> type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct PointerTraits {
|
|
|
|
typedef T pointer;
|
|
|
|
|
2015-04-27 18:38:34 +00:00
|
|
|
typedef typename __OctaPtrTraitsElementType <T>::type element_type;
|
|
|
|
typedef typename __OctaPtrTraitsDifferenceType<T>::type difference_type;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
template<typename U>
|
|
|
|
using rebind = typename __OctaPtrTraitsRebind<T, U>::type;
|
|
|
|
|
|
|
|
private:
|
2015-04-27 19:23:38 +00:00
|
|
|
struct __OctaNat {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
public:
|
2015-04-27 18:38:34 +00:00
|
|
|
static T pointer_to(Conditional<IsVoid<element_type>::value,
|
2015-04-27 19:23:38 +00:00
|
|
|
__OctaNat, element_type
|
2015-04-28 01:20:14 +00:00
|
|
|
> &r) noexcept(noexcept(T::pointer_to(r))) {
|
2015-04-27 17:56:17 +00:00
|
|
|
return T::pointer_to(r);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct PointerTraits<T *> {
|
|
|
|
typedef T *pointer;
|
2015-04-27 18:38:34 +00:00
|
|
|
typedef T element_type;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-27 18:38:34 +00:00
|
|
|
typedef ptrdiff_t difference_type;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
template<typename U> using rebind = U *;
|
|
|
|
|
|
|
|
private:
|
2015-04-27 19:23:38 +00:00
|
|
|
struct __OctaNat {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
public:
|
2015-04-27 18:38:34 +00:00
|
|
|
static T pointer_to(Conditional<IsVoid<element_type>::value,
|
2015-04-27 19:23:38 +00:00
|
|
|
__OctaNat, element_type
|
2015-04-28 01:20:14 +00:00
|
|
|
> &r) noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
return octa::address_of(r);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* default deleter */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct DefaultDelete {
|
|
|
|
constexpr DefaultDelete() = default;
|
|
|
|
|
|
|
|
template<typename U> DefaultDelete(const DefaultDelete<U> &) {};
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
void operator()(T *p) const noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
delete p;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct DefaultDelete<T[]> {
|
|
|
|
constexpr DefaultDelete() = default;
|
|
|
|
|
|
|
|
template<typename U> DefaultDelete(const DefaultDelete<U[]> &) {};
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
void operator()(T *p) const noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
delete[] p;
|
|
|
|
}
|
|
|
|
template<typename U> void operator()(U *) const = delete;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* box */
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static int __octa_ptr_test(...);
|
|
|
|
template<typename T>
|
2015-04-27 18:38:34 +00:00
|
|
|
static char __octa_ptr_test(typename T::pointer * = 0);
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
template<typename T> struct __OctaHasPtr: IntegralConstant<bool,
|
|
|
|
(sizeof(__octa_ptr_test<T>(0)) == 1)
|
|
|
|
> {};
|
|
|
|
|
|
|
|
template<typename T, typename D, bool = __OctaHasPtr<D>::value>
|
|
|
|
struct __OctaPtrTypeBase {
|
2015-04-27 18:38:34 +00:00
|
|
|
typedef typename D::pointer type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename D> struct __OctaPtrTypeBase<T, D, false> {
|
|
|
|
typedef T *type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename D> struct __OctaPtrType {
|
|
|
|
typedef typename __OctaPtrTypeBase<T, RemoveReference<D>>::type type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename D = DefaultDelete<T>>
|
|
|
|
struct Box {
|
2015-04-27 18:38:34 +00:00
|
|
|
typedef T element_type;
|
|
|
|
typedef D deleter_type;
|
|
|
|
typedef typename __OctaPtrType<T, D>::type pointer;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
private:
|
2015-04-27 19:23:38 +00:00
|
|
|
struct __OctaNat { int x; };
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
typedef RemoveReference<D> &D_ref;
|
|
|
|
typedef const RemoveReference<D> &D_cref;
|
|
|
|
|
|
|
|
public:
|
2015-04-28 01:20:14 +00:00
|
|
|
constexpr Box() noexcept: p_ptr(nullptr), p_del() {
|
2015-04-27 17:56:17 +00:00
|
|
|
static_assert(!IsPointer<D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
2015-04-28 01:20:14 +00:00
|
|
|
constexpr Box(nullptr_t) noexcept: p_ptr(nullptr), p_del() {
|
2015-04-27 17:56:17 +00:00
|
|
|
static_assert(!IsPointer<D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
explicit Box(pointer p) noexcept: p_ptr(p), p_del() {
|
2015-04-27 17:56:17 +00:00
|
|
|
static_assert(!IsPointer<D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
|
|
|
|
2015-04-27 18:38:34 +00:00
|
|
|
Box(pointer p, Conditional<IsReference<D>::value,
|
2015-04-27 17:56:17 +00:00
|
|
|
D, AddLvalueReference<const D>
|
2015-04-28 01:20:14 +00:00
|
|
|
> d) noexcept: p_ptr(p), p_del(d) {}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
Box(pointer p, RemoveReference<D> &&d) noexcept: p_ptr(p), p_del(move(d)) {
|
2015-04-27 17:56:17 +00:00
|
|
|
static_assert(!IsReference<D>::value,
|
|
|
|
"rvalue deleter cannot be a ref");
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
Box(Box &&u) noexcept: p_ptr(u.release()), p_del(forward<D>(u.get_deleter())) {}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
template<typename TT, typename DD>
|
|
|
|
Box(Box<TT, DD> &&u, EnableIf<!IsArray<TT>::value
|
2015-04-27 18:38:34 +00:00
|
|
|
&& IsConvertible<typename Box<TT, DD>::pointer, pointer>::value
|
2015-04-27 17:56:17 +00:00
|
|
|
&& IsConvertible<DD, D>::value
|
|
|
|
&& (!IsReference<D>::value || IsSame<D, DD>::value)
|
2015-04-28 01:20:14 +00:00
|
|
|
> = __OctaNat()) noexcept: p_ptr(u.release()),
|
2015-04-27 17:56:17 +00:00
|
|
|
p_del(forward<DD>(u.get_deleter())) {}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
Box &operator=(Box &&u) noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
reset(u.release());
|
|
|
|
p_del = forward<D>(u.get_deleter());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename TT, typename DD>
|
|
|
|
EnableIf<!IsArray<TT>::value
|
2015-04-27 18:38:34 +00:00
|
|
|
&& IsConvertible<typename Box<TT, DD>::pointer, pointer>::value
|
2015-04-27 17:56:17 +00:00
|
|
|
&& IsAssignable<D &, DD &&>::value,
|
|
|
|
Box &
|
2015-04-28 01:20:14 +00:00
|
|
|
> operator=(Box<TT, DD> &&u) noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
reset(u.release());
|
|
|
|
p_del = forward<DD>(u.get_deleter());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
Box &operator=(nullptr_t) noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
reset();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
~Box() { reset(); }
|
|
|
|
|
|
|
|
AddLvalueReference<T> operator*() const { return *p_ptr; }
|
2015-04-28 01:20:14 +00:00
|
|
|
pointer operator->() const noexcept { return p_ptr; }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
explicit operator bool() const noexcept { return p_ptr != nullptr; }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
pointer get() const noexcept { return p_ptr; }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
D_ref get_deleter() noexcept { return p_del; }
|
|
|
|
D_cref get_deleter() const noexcept { return p_del; }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
pointer release() noexcept {
|
2015-04-27 18:38:34 +00:00
|
|
|
pointer p = p_ptr;
|
2015-04-27 17:56:17 +00:00
|
|
|
p_ptr = nullptr;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
void reset(pointer p = nullptr) noexcept {
|
2015-04-27 18:38:34 +00:00
|
|
|
pointer tmp = p_ptr;
|
2015-04-27 17:56:17 +00:00
|
|
|
p_ptr = p;
|
|
|
|
if (tmp) p_del(tmp);
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
void swap(Box &u) noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
octa::swap(p_ptr, u.p_ptr);
|
|
|
|
octa::swap(p_del, u.p_del);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
/* TODO: optimize with pair (so that deleter doesn't take up memory) */
|
|
|
|
T *p_ptr;
|
|
|
|
D p_del;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename U, bool = IsSame<
|
2015-04-27 19:23:38 +00:00
|
|
|
RemoveCv<typename PointerTraits<T>::element_type>,
|
|
|
|
RemoveCv<typename PointerTraits<U>::element_type>
|
|
|
|
>::value> struct __OctaSameOrLessCvQualifiedBase: IsConvertible<T, U> {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
template<typename T, typename U>
|
2015-04-27 19:23:38 +00:00
|
|
|
struct __OctaSameOrLessCvQualifiedBase<T, U, false>: False {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
template<typename T, typename U, bool = IsPointer<T>::value
|
|
|
|
|| IsSame<T, U>::value || __OctaHasElementType<T>::value
|
2015-04-27 19:23:38 +00:00
|
|
|
> struct __OctaSameOrLessCvQualified: __OctaSameOrLessCvQualifiedBase<T, U> {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
template<typename T, typename U>
|
2015-04-27 19:23:38 +00:00
|
|
|
struct __OctaSameOrLessCvQualified<T, U, false>: False {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
template<typename T, typename D>
|
|
|
|
struct Box<T[], D> {
|
2015-04-27 18:38:34 +00:00
|
|
|
typedef T element_type;
|
|
|
|
typedef D deleter_type;
|
|
|
|
typedef typename __OctaPtrType<T, D>::type pointer;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
private:
|
2015-04-27 19:23:38 +00:00
|
|
|
struct __OctaNat { int x; };
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
typedef RemoveReference<D> &D_ref;
|
|
|
|
typedef const RemoveReference<D> &D_cref;
|
|
|
|
|
|
|
|
public:
|
2015-04-28 01:20:14 +00:00
|
|
|
constexpr Box() noexcept: p_ptr(nullptr), p_del() {
|
2015-04-27 17:56:17 +00:00
|
|
|
static_assert(!IsPointer<D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
2015-04-28 01:20:14 +00:00
|
|
|
constexpr Box(nullptr_t) noexcept: p_ptr(nullptr), p_del() {
|
2015-04-27 17:56:17 +00:00
|
|
|
static_assert(!IsPointer<D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
|
|
|
|
2015-04-27 18:38:34 +00:00
|
|
|
template<typename U> explicit Box(U p, EnableIf<
|
2015-04-27 19:23:38 +00:00
|
|
|
__OctaSameOrLessCvQualified<U, pointer>::value, __OctaNat
|
2015-04-28 01:20:14 +00:00
|
|
|
> = __OctaNat()) noexcept: p_ptr(p), p_del() {
|
2015-04-27 17:56:17 +00:00
|
|
|
static_assert(!IsPointer<D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
|
|
|
|
2015-04-27 18:38:34 +00:00
|
|
|
template<typename U> Box(U p, Conditional<IsReference<D>::value,
|
2015-04-27 17:56:17 +00:00
|
|
|
D, AddLvalueReference<const D>
|
2015-04-27 19:23:38 +00:00
|
|
|
> d, EnableIf<__OctaSameOrLessCvQualified<U, pointer>::value, __OctaNat
|
2015-04-28 01:20:14 +00:00
|
|
|
> = __OctaNat()) noexcept: p_ptr(p), p_del(d) {}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
Box(nullptr_t, Conditional<IsReference<D>::value,
|
|
|
|
D, AddLvalueReference<const D>
|
2015-04-28 01:20:14 +00:00
|
|
|
> d) noexcept: p_ptr(), p_del(d) {}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-27 18:38:34 +00:00
|
|
|
template<typename U> Box(U p, RemoveReference<D> &&d, EnableIf<
|
2015-04-27 19:23:38 +00:00
|
|
|
__OctaSameOrLessCvQualified<U, pointer>::value, __OctaNat
|
2015-04-28 01:20:14 +00:00
|
|
|
> = __OctaNat()) noexcept: p_ptr(p), p_del(move(d)) {
|
2015-04-27 17:56:17 +00:00
|
|
|
static_assert(!IsReference<D>::value,
|
|
|
|
"rvalue deleter cannot be a ref");
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
Box(nullptr_t, RemoveReference<D> &&d) noexcept: p_ptr(), p_del(move(d)) {
|
2015-04-27 17:56:17 +00:00
|
|
|
static_assert(!IsReference<D>::value,
|
|
|
|
"rvalue deleter cannot be a ref");
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
Box(Box &&u) noexcept: p_ptr(u.release()), p_del(forward<D>(u.get_deleter())) {}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
|
|
|
template<typename TT, typename DD>
|
|
|
|
Box(Box<TT, DD> &&u, EnableIf<IsArray<TT>::value
|
2015-04-27 19:23:38 +00:00
|
|
|
&& __OctaSameOrLessCvQualified<typename Box<TT, DD>::pointer,
|
2015-04-27 18:38:34 +00:00
|
|
|
pointer>::value
|
2015-04-27 17:56:17 +00:00
|
|
|
&& IsConvertible<DD, D>::value
|
2015-04-27 19:23:38 +00:00
|
|
|
&& (!IsReference<D>::value || IsSame<D, DD>::value)> = __OctaNat()
|
2015-04-28 01:20:14 +00:00
|
|
|
) noexcept: p_ptr(u.release()), p_del(forward<DD>(u.get_deleter())) {}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
Box &operator=(Box &&u) noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
reset(u.release());
|
|
|
|
p_del = forward<D>(u.get_deleter());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename TT, typename DD>
|
|
|
|
EnableIf<IsArray<TT>::value
|
2015-04-27 19:23:38 +00:00
|
|
|
&& __OctaSameOrLessCvQualified<typename Box<TT, DD>::pointer,
|
2015-04-27 18:38:34 +00:00
|
|
|
pointer>::value
|
2015-04-27 17:56:17 +00:00
|
|
|
&& IsAssignable<D &, DD &&>::value,
|
|
|
|
Box &
|
2015-04-28 01:20:14 +00:00
|
|
|
> operator=(Box<TT, DD> &&u) noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
reset(u.release());
|
|
|
|
p_del = forward<DD>(u.get_deleter());
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
Box &operator=(nullptr_t) noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
reset();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
~Box() { reset(); }
|
|
|
|
|
|
|
|
AddLvalueReference<T> operator[](size_t idx) const {
|
|
|
|
return p_ptr[idx];
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
explicit operator bool() const noexcept { return p_ptr != nullptr; }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
pointer get() const noexcept { return p_ptr; }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
D_ref get_deleter() noexcept { return p_del; }
|
|
|
|
D_cref get_deleter() const noexcept { return p_del; }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
pointer release() noexcept {
|
2015-04-27 18:38:34 +00:00
|
|
|
pointer p = p_ptr;
|
2015-04-27 17:56:17 +00:00
|
|
|
p_ptr = nullptr;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename U> EnableIf<
|
2015-04-27 19:23:38 +00:00
|
|
|
__OctaSameOrLessCvQualified<U, pointer>::value, void
|
2015-04-28 01:20:14 +00:00
|
|
|
> reset(U p) noexcept {
|
2015-04-27 18:38:34 +00:00
|
|
|
pointer tmp = p_ptr;
|
2015-04-27 17:56:17 +00:00
|
|
|
p_ptr = p;
|
|
|
|
if (tmp) p_del(tmp);
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
void reset(nullptr_t) noexcept {
|
2015-04-27 18:38:34 +00:00
|
|
|
pointer tmp = p_ptr;
|
2015-04-27 17:56:17 +00:00
|
|
|
p_ptr = nullptr;
|
|
|
|
if (tmp) p_del(tmp);
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
void reset() noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
reset(nullptr);
|
|
|
|
}
|
|
|
|
|
2015-04-28 01:20:14 +00:00
|
|
|
void swap(Box &u) noexcept {
|
2015-04-27 17:56:17 +00:00
|
|
|
octa::swap(p_ptr, u.p_ptr);
|
|
|
|
octa::swap(p_del, u.p_del);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
T *p_ptr;
|
|
|
|
D p_del;
|
|
|
|
};
|
2015-04-27 19:05:33 +00:00
|
|
|
|
|
|
|
template<typename T> struct __OctaBoxIf {
|
|
|
|
typedef Box<T> __OctaBox;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T> struct __OctaBoxIf<T[]> {
|
|
|
|
typedef Box<T[]> __OctaBoxUnknownSize;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, size_t N> struct __OctaBoxIf<T[N]> {
|
|
|
|
typedef void __OctaBoxKnownSize;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
|
|
|
typename __OctaBoxIf<T>::__OctaBox make_box(A &&...args) {
|
|
|
|
return Box<T>(new T(forward<A>(args)...));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
typename __OctaBoxIf<T>::__OctaBoxUnknownSize make_box(size_t n) {
|
|
|
|
return Box<T>(new RemoveExtent<T>[n]());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename ...A>
|
|
|
|
typename __OctaBoxIf<T>::__OctaBoxKnownSize make_box(A &&...args) = delete;
|
2015-04-18 18:02:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|