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-05-13 19:56:36 +00:00
|
|
|
#include <stddef.h>
|
|
|
|
|
2015-04-27 17:56:17 +00:00
|
|
|
#include "octa/new.h"
|
2015-05-10 20:57:52 +00:00
|
|
|
#include "octa/utility.h"
|
2015-04-27 17:56:17 +00:00
|
|
|
#include "octa/type_traits.h"
|
|
|
|
|
2015-04-18 18:02:44 +00:00
|
|
|
namespace octa {
|
2015-06-04 01:20:20 +00:00
|
|
|
/* address of */
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T> constexpr _T *address_of(_T &v) {
|
|
|
|
return reinterpret_cast<_T *>(&const_cast<char &>
|
|
|
|
(reinterpret_cast<const volatile char &>(v)));
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
/* pointer traits */
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
namespace detail {
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct HasElement {
|
|
|
|
template<typename _U> static int test(...);
|
|
|
|
template<typename _U> static char test(typename _U::Element * = 0);
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T, bool = HasElement<_T>::value>
|
|
|
|
struct PointerElementBase;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T> struct PointerElementBase<_T, true> {
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef typename _T::Element Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<template<typename, typename...> class _T, typename _U, typename ..._A>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerElementBase<_T<_U, _A...>, true> {
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef typename _T<_U, _A...>::Element Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<template<typename, typename...> class _T, typename _U, typename ..._A>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerElementBase<_T<_U, _A...>, false> {
|
2015-06-01 23:57:34 +00:00
|
|
|
typedef _U Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerElementType {
|
|
|
|
typedef typename PointerElementBase<_T>::Type Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _T>
|
|
|
|
struct PointerElementType<_T *> {
|
|
|
|
typedef _T Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _T>
|
|
|
|
struct HasDifference {
|
|
|
|
template<typename _U> static int test(...);
|
|
|
|
template<typename _U> static char test(typename _U::Difference * = 0);
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T, bool = HasDifference<_T>::value>
|
|
|
|
struct PointerDifferenceBase {
|
2015-05-03 22:50:09 +00:00
|
|
|
typedef ptrdiff_t Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T> struct PointerDifferenceBase<_T, true> {
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef typename _T::Difference Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct PointerDifferenceType {
|
|
|
|
typedef typename PointerDifferenceBase<_T>::Type Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _T>
|
|
|
|
struct PointerDifferenceType<_T *> {
|
|
|
|
typedef ptrdiff_t Type;
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _U>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct HasRebind {
|
|
|
|
template<typename _V> static int test(...);
|
|
|
|
template<typename _V> static char test(
|
|
|
|
typename _V::template Rebind<_U> * = 0);
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T, typename _U, bool = HasRebind<_T, _U>::value>
|
|
|
|
struct PointerRebindBase {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef typename _T::template Rebind<_U> Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<template<typename, typename...> class _T, typename _U,
|
|
|
|
typename ..._A, typename _V
|
2015-04-27 17:56:17 +00:00
|
|
|
>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerRebindBase<_T<_U, _A...>, _V, true> {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef typename _T<_U, _A...>::template Rebind<_V> Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<template<typename, typename...> class _T, typename _U,
|
|
|
|
typename ..._A, typename _V
|
2015-04-27 17:56:17 +00:00
|
|
|
>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerRebindBase<_T<_U, _A...>, _V, false> {
|
2015-06-01 23:57:34 +00:00
|
|
|
typedef _T<_V, _A...> Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T, typename _U>
|
|
|
|
struct PointerRebindType {
|
|
|
|
using type = typename PointerRebindBase<_T, _U>::Type;
|
2015-05-03 21:39:32 +00:00
|
|
|
};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T, typename _U>
|
|
|
|
struct PointerRebindType<_T *, _U> {
|
|
|
|
using type = _U *;
|
2015-05-03 21:39:32 +00:00
|
|
|
};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerPointer {
|
2015-06-01 23:57:34 +00:00
|
|
|
typedef _T Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerPointer<_T *> {
|
|
|
|
typedef _T *Type;
|
2015-05-03 21:39:32 +00:00
|
|
|
};
|
2015-06-04 01:20:20 +00:00
|
|
|
} /*namespace detail */
|
2015-05-03 21:39:32 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T>
|
|
|
|
using Pointer = typename octa::detail::PointerPointer<_T>::Type;
|
2015-05-03 21:39:32 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T>
|
|
|
|
using PointerElement = typename octa::detail::PointerElementType<_T>::Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T>
|
|
|
|
using PointerDifference = typename octa::detail::PointerDifferenceType<_T>::Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T, typename _U>
|
|
|
|
using PointerRebind = typename octa::detail::PointerRebindType<_T, _U>::Type;
|
2015-05-03 21:39:32 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
/* pointer to */
|
2015-05-03 21:39:32 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
namespace detail {
|
|
|
|
struct PointerToNat {};
|
2015-05-03 21:39:32 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerTo {
|
2015-06-01 23:57:34 +00:00
|
|
|
static _T pointer_to(octa::Conditional<
|
|
|
|
octa::IsVoid<PointerElement<_T>>::value,
|
2015-06-04 01:20:20 +00:00
|
|
|
PointerToNat, PointerElement<_T>
|
|
|
|
> &r) {
|
|
|
|
return _T::pointer_to(r);
|
2015-05-03 21:39:32 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerTo<_T *> {
|
2015-06-01 23:57:34 +00:00
|
|
|
static _T pointer_to(octa::Conditional<
|
2015-06-04 01:20:20 +00:00
|
|
|
octa::IsVoid<_T>::value, PointerToNat, _T
|
|
|
|
> &r) {
|
|
|
|
return octa::address_of(r);
|
2015-04-27 17:56:17 +00:00
|
|
|
}
|
|
|
|
};
|
2015-06-04 01:20:20 +00:00
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T>
|
|
|
|
static _T pointer_to(octa::Conditional<
|
|
|
|
octa::IsVoid<PointerElement<_T>>::value,
|
|
|
|
octa::detail::PointerToNat, PointerElement<_T>
|
|
|
|
> &r) {
|
|
|
|
return octa::detail::PointerTo<_T>::pointer_to(r);
|
|
|
|
}
|
2015-05-03 21:39:32 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
/* default deleter */
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct DefaultDelete {
|
|
|
|
constexpr DefaultDelete() = default;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _U> DefaultDelete(const DefaultDelete<_U> &) {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
void operator()(_T *p) const {
|
|
|
|
delete p;
|
|
|
|
}
|
|
|
|
};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T>
|
|
|
|
struct DefaultDelete<_T[]> {
|
|
|
|
constexpr DefaultDelete() = default;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _U> DefaultDelete(const DefaultDelete<_U[]> &) {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
void operator()(_T *p) const {
|
|
|
|
delete[] p;
|
|
|
|
}
|
|
|
|
template<typename _U> void operator()(_U *) const = delete;
|
|
|
|
};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:20:20 +00:00
|
|
|
/* box */
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
namespace detail {
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _U, bool = octa::IsEmpty<_U>::value>
|
2015-06-04 01:09:07 +00:00
|
|
|
struct BoxPair;
|
2015-04-30 17:53:38 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _U>
|
2015-06-04 01:09:07 +00:00
|
|
|
struct BoxPair<_T, _U, false> { /* non-empty deleter */
|
|
|
|
_T *p_ptr;
|
2015-04-30 17:53:38 +00:00
|
|
|
private:
|
2015-06-04 01:09:07 +00:00
|
|
|
_U p_del;
|
2015-04-30 17:53:38 +00:00
|
|
|
|
|
|
|
public:
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _D>
|
2015-06-04 01:09:07 +00:00
|
|
|
BoxPair(_T *ptr, _D &&dltr): p_ptr(ptr), p_del(octa::forward<_D>(dltr)) {}
|
2015-04-30 17:53:38 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
_U &get_deleter() { return p_del; }
|
|
|
|
const _U &get_deleter() const { return p_del; }
|
2015-04-30 17:53:38 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
void swap(BoxPair &v) {
|
|
|
|
octa::swap(p_ptr, v.p_ptr);
|
|
|
|
octa::swap(p_del, v.p_del);
|
2015-04-30 17:53:38 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _U>
|
2015-06-04 01:09:07 +00:00
|
|
|
struct BoxPair<_T, _U, true>: _U { /* empty deleter */
|
|
|
|
_T *p_ptr;
|
2015-04-30 17:53:38 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _D>
|
2015-06-04 01:09:07 +00:00
|
|
|
BoxPair(_T *ptr, _D &&dltr): _U(octa::forward<_D>(dltr)), p_ptr(ptr) {}
|
2015-04-30 17:53:38 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
_U &get_deleter() { return *this; }
|
|
|
|
const _U &get_deleter() const { return *this; }
|
2015-04-30 17:53:38 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
void swap(BoxPair &v) {
|
|
|
|
octa::swap(p_ptr, v.p_ptr);
|
2015-04-30 17:53:38 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-06-04 01:09:07 +00:00
|
|
|
static int ptr_test(...);
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T>
|
2015-06-04 01:09:07 +00:00
|
|
|
static char ptr_test(typename _T::Pointer * = 0);
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T> struct HasPtr: octa::IntegralConstant<bool,
|
|
|
|
(sizeof(ptr_test<_T>(0)) == 1)
|
2015-04-27 17:56:17 +00:00
|
|
|
> {};
|
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T, typename _D, bool = HasPtr<_D>::value>
|
|
|
|
struct PointerBase {
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef typename _D::Pointer Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T, typename _D> struct PointerBase<_T, _D, false> {
|
2015-06-01 23:57:34 +00:00
|
|
|
typedef _T *Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T, typename _D> struct PointerType {
|
|
|
|
typedef typename PointerBase<_T, octa::RemoveReference<_D>>::Type Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
2015-06-04 01:09:07 +00:00
|
|
|
} /* namespace detail */
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T, typename _D = DefaultDelete<_T>>
|
|
|
|
struct Box {
|
|
|
|
typedef _T Element;
|
|
|
|
typedef _D Deleter;
|
|
|
|
typedef typename octa::detail::PointerType<_T, _D>::Type Pointer;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
private:
|
|
|
|
struct Nat { int x; };
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
typedef RemoveReference<_D> &_D_ref;
|
|
|
|
typedef const RemoveReference<_D> &_D_cref;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
public:
|
|
|
|
constexpr Box(): p_stor(nullptr, _D()) {
|
|
|
|
static_assert(!octa::IsPointer<_D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
|
|
|
constexpr Box(nullptr_t): p_stor(nullptr, _D()) {
|
|
|
|
static_assert(!octa::IsPointer<_D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
explicit Box(Pointer p): p_stor(p, _D()) {
|
|
|
|
static_assert(!octa::IsPointer<_D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Box(Pointer p, octa::Conditional<octa::IsReference<_D>::value,
|
|
|
|
_D, octa::AddLvalueReference<const _D>
|
|
|
|
> d): p_stor(p, d) {}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Box(Pointer p, octa::RemoveReference<_D> &&d):
|
|
|
|
p_stor(p, octa::move(d)) {
|
|
|
|
static_assert(!octa::IsReference<_D>::value,
|
|
|
|
"rvalue deleter cannot be a ref");
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Box(Box &&u): p_stor(u.release(), octa::forward<_D>(u.get_deleter())) {}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _TT, typename _DD>
|
|
|
|
Box(Box<_TT, _DD> &&u, octa::EnableIf<!octa::IsArray<_TT>::value
|
|
|
|
&& octa::IsConvertible<typename Box<_TT, _DD>::Pointer, Pointer>::value
|
|
|
|
&& octa::IsConvertible<_DD, _D>::value
|
|
|
|
&& (!octa::IsReference<_D>::value || octa::IsSame<_D, _DD>::value)
|
|
|
|
> = Nat()): p_stor(u.release(), octa::forward<_DD>(u.get_deleter())) {}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Box &operator=(Box &&u) {
|
|
|
|
reset(u.release());
|
|
|
|
p_stor.get_deleter() = octa::forward<_D>(u.get_deleter());
|
|
|
|
return *this;
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _TT, typename _DD>
|
|
|
|
EnableIf<!octa::IsArray<_TT>::value
|
|
|
|
&& octa::IsConvertible<typename Box<_TT, _DD>::Pointer, Pointer>::value
|
|
|
|
&& octa::IsAssignable<_D &, _DD &&>::value,
|
|
|
|
Box &
|
|
|
|
> operator=(Box<_TT, _DD> &&u) {
|
|
|
|
reset(u.release());
|
|
|
|
p_stor.get_deleter() = octa::forward<_DD>(u.get_deleter());
|
|
|
|
return *this;
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Box &operator=(nullptr_t) {
|
|
|
|
reset();
|
|
|
|
return *this;
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
~Box() { reset(); }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
octa::AddLvalueReference<_T> operator*() const { return *p_stor.p_ptr; }
|
|
|
|
Pointer operator->() const { return p_stor.p_ptr; }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
explicit operator bool() const {
|
|
|
|
return p_stor.p_ptr != nullptr;
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Pointer get() const { return p_stor.p_ptr; }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
_D_ref get_deleter() { return p_stor.get_deleter(); }
|
|
|
|
_D_cref get_deleter() const { return p_stor.get_deleter(); }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Pointer release() {
|
|
|
|
Pointer p = p_stor.p_ptr;
|
|
|
|
p_stor.p_ptr = nullptr;
|
|
|
|
return p;
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
void reset(Pointer p = nullptr) {
|
|
|
|
Pointer tmp = p_stor.p_ptr;
|
|
|
|
p_stor.p_ptr = p;
|
|
|
|
if (tmp) p_stor.get_deleter()(tmp);
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
void swap(Box &u) {
|
|
|
|
p_stor.swap(u.p_stor);
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
private:
|
|
|
|
octa::detail::BoxPair<_T, _D> p_stor;
|
|
|
|
};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
namespace detail {
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _U, bool = octa::IsSame<
|
|
|
|
octa::RemoveCv<PointerElement<_T>>,
|
|
|
|
octa::RemoveCv<PointerElement<_U>>
|
2015-06-04 01:09:07 +00:00
|
|
|
>::value> struct SameOrLessCvQualifiedBase: octa::IsConvertible<_T, _U> {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _U>
|
2015-06-04 01:09:07 +00:00
|
|
|
struct SameOrLessCvQualifiedBase<_T, _U, false>: octa::False {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _U, bool = octa::IsPointer<_T>::value
|
2015-06-04 01:20:20 +00:00
|
|
|
|| octa::IsSame<_T, _U>::value || octa::detail::HasElement<_T>::value
|
2015-06-04 01:09:07 +00:00
|
|
|
> struct SameOrLessCvQualified: SameOrLessCvQualifiedBase<_T, _U> {};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-01 23:57:34 +00:00
|
|
|
template<typename _T, typename _U>
|
2015-06-04 01:09:07 +00:00
|
|
|
struct SameOrLessCvQualified<_T, _U, false>: octa::False {};
|
|
|
|
} /* namespace detail */
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T, typename _D>
|
|
|
|
struct Box<_T[], _D> {
|
|
|
|
typedef _T Element;
|
|
|
|
typedef _D Deleter;
|
|
|
|
typedef typename octa::detail::PointerType<_T, _D>::Type Pointer;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
private:
|
|
|
|
struct Nat { int x; };
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
typedef RemoveReference<_D> &_D_ref;
|
|
|
|
typedef const RemoveReference<_D> &_D_cref;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
public:
|
|
|
|
constexpr Box(): p_stor(nullptr, _D()) {
|
|
|
|
static_assert(!octa::IsPointer<_D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
|
|
|
constexpr Box(nullptr_t): p_stor(nullptr, _D()) {
|
|
|
|
static_assert(!octa::IsPointer<_D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _U> explicit Box(_U p, octa::EnableIf<
|
|
|
|
octa::detail::SameOrLessCvQualified<_U, Pointer>::value, Nat
|
|
|
|
> = Nat()): p_stor(p, _D()) {
|
|
|
|
static_assert(!octa::IsPointer<_D>::value,
|
|
|
|
"Box constructed with null fptr deleter");
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _U> Box(_U p, octa::Conditional<
|
|
|
|
octa::IsReference<_D>::value,
|
|
|
|
_D, AddLvalueReference<const _D>
|
|
|
|
> d, octa::EnableIf<octa::detail::SameOrLessCvQualified<_U, Pointer>::value,
|
|
|
|
Nat> = Nat()): p_stor(p, d) {}
|
|
|
|
|
|
|
|
Box(nullptr_t, octa::Conditional<octa::IsReference<_D>::value,
|
|
|
|
_D, AddLvalueReference<const _D>
|
|
|
|
> d): p_stor(nullptr, d) {}
|
|
|
|
|
|
|
|
template<typename _U> Box(_U p, octa::RemoveReference<_D> &&d,
|
|
|
|
octa::EnableIf<
|
|
|
|
octa::detail::SameOrLessCvQualified<_U, Pointer>::value, Nat
|
|
|
|
> = Nat()): p_stor(p, octa::move(d)) {
|
|
|
|
static_assert(!octa::IsReference<_D>::value,
|
|
|
|
"rvalue deleter cannot be a ref");
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Box(nullptr_t, octa::RemoveReference<_D> &&d):
|
|
|
|
p_stor(nullptr, octa::move(d)) {
|
|
|
|
static_assert(!octa::IsReference<_D>::value,
|
|
|
|
"rvalue deleter cannot be a ref");
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Box(Box &&u): p_stor(u.release(), octa::forward<_D>(u.get_deleter())) {}
|
|
|
|
|
|
|
|
template<typename _TT, typename _DD>
|
|
|
|
Box(Box<_TT, _DD> &&u, EnableIf<IsArray<_TT>::value
|
|
|
|
&& octa::detail::SameOrLessCvQualified<typename Box<_TT, _DD>::Pointer,
|
|
|
|
Pointer>::value
|
|
|
|
&& octa::IsConvertible<_DD, _D>::value
|
|
|
|
&& (!octa::IsReference<_D>::value ||
|
|
|
|
octa::IsSame<_D, _DD>::value)> = Nat()
|
|
|
|
): p_stor(u.release(), octa::forward<_DD>(u.get_deleter())) {}
|
|
|
|
|
|
|
|
Box &operator=(Box &&u) {
|
|
|
|
reset(u.release());
|
|
|
|
p_stor.get_deleter() = octa::forward<_D>(u.get_deleter());
|
|
|
|
return *this;
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _TT, typename _DD>
|
|
|
|
EnableIf<octa::IsArray<_TT>::value
|
|
|
|
&& octa::detail::SameOrLessCvQualified<typename Box<_TT, _DD>::Pointer,
|
|
|
|
Pointer>::value
|
|
|
|
&& IsAssignable<_D &, _DD &&>::value,
|
|
|
|
Box &
|
|
|
|
> operator=(Box<_TT, _DD> &&u) {
|
|
|
|
reset(u.release());
|
|
|
|
p_stor.get_deleter() = octa::forward<_DD>(u.get_deleter());
|
|
|
|
return *this;
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Box &operator=(nullptr_t) {
|
|
|
|
reset();
|
|
|
|
return *this;
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
~Box() { reset(); }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
octa::AddLvalueReference<_T> operator[](size_t idx) const {
|
|
|
|
return p_stor.p_ptr[idx];
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
explicit operator bool() const {
|
|
|
|
return p_stor.p_ptr != nullptr;
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Pointer get() const { return p_stor.p_ptr; }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
_D_ref get_deleter() { return p_stor.get_deleter(); }
|
|
|
|
_D_cref get_deleter() const { return p_stor.get_deleter(); }
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
Pointer release() {
|
|
|
|
Pointer p = p_stor.p_ptr;
|
|
|
|
p_stor.p_ptr = nullptr;
|
|
|
|
return p;
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _U> EnableIf<
|
|
|
|
octa::detail::SameOrLessCvQualified<_U, Pointer>::value, void
|
|
|
|
> reset(_U p) {
|
|
|
|
Pointer tmp = p_stor.p_ptr;
|
|
|
|
p_stor.p_ptr = p;
|
|
|
|
if (tmp) p_stor.get_deleter()(tmp);
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
void reset(nullptr_t) {
|
|
|
|
Pointer tmp = p_stor.p_ptr;
|
|
|
|
p_stor.p_ptr = nullptr;
|
|
|
|
if (tmp) p_stor.get_deleter()(tmp);
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
void reset() {
|
|
|
|
reset(nullptr);
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
void swap(Box &u) {
|
|
|
|
p_stor.swap(u.p_stor);
|
|
|
|
}
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
private:
|
|
|
|
octa::detail::BoxPair<_T, _D> p_stor;
|
|
|
|
};
|
2015-04-27 19:05:33 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
namespace detail {
|
|
|
|
template<typename _T> struct BoxIf {
|
2015-06-04 20:08:56 +00:00
|
|
|
typedef octa::Box<_T> Box;
|
2015-04-27 19:05:33 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T> struct BoxIf<_T[]> {
|
2015-06-04 20:08:56 +00:00
|
|
|
typedef octa::Box<_T[]> BoxUnknownSize;
|
2015-04-27 19:05:33 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T, size_t _N> struct BoxIf<_T[_N]> {
|
|
|
|
typedef void BoxKnownSize;
|
2015-04-27 19:05:33 +00:00
|
|
|
};
|
2015-06-04 01:09:07 +00:00
|
|
|
}
|
2015-04-27 19:05:33 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T, typename ..._A>
|
|
|
|
typename octa::detail::BoxIf<_T>::Box make_box(_A &&...args) {
|
|
|
|
return Box<_T>(new _T(octa::forward<_A>(args)...));
|
|
|
|
}
|
2015-04-27 19:05:33 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T>
|
|
|
|
typename octa::detail::BoxIf<_T>::BoxUnknownSize make_box(size_t n) {
|
|
|
|
return Box<_T>(new octa::RemoveExtent<_T>[n]());
|
|
|
|
}
|
2015-04-27 19:05:33 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
template<typename _T, typename ..._A>
|
|
|
|
typename octa::detail::BoxIf<_T>::BoxKnownSize make_box(_A &&...args) = delete;
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
/* allocator */
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename> struct Allocator;
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<> struct Allocator<void> {
|
|
|
|
typedef void Value;
|
|
|
|
typedef void *Pointer;
|
|
|
|
typedef const void *ConstPointer;
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U> using Rebind = Allocator<_U>;
|
|
|
|
};
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<> struct Allocator<const void> {
|
|
|
|
typedef const void Value;
|
|
|
|
typedef const void *Pointer;
|
|
|
|
typedef const void *ConstPointer;
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U> using Rebind = Allocator<_U>;
|
|
|
|
};
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _T> struct Allocator {
|
|
|
|
typedef size_t Size;
|
|
|
|
typedef ptrdiff_t Difference;
|
|
|
|
typedef _T Value;
|
|
|
|
typedef _T &Reference;
|
|
|
|
typedef const _T &ConstReference;
|
|
|
|
typedef _T *Pointer;
|
|
|
|
typedef const _T *ConstPointer;
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U> using Rebind = Allocator<_U>;
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
Pointer address(Reference v) const {
|
|
|
|
return address_of(v);
|
|
|
|
};
|
|
|
|
ConstPointer address(ConstReference v) const {
|
|
|
|
return address_of(v);
|
|
|
|
};
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
Size max_size() const { return Size(~0) / sizeof(_T); }
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
Pointer allocate(Size n, Allocator<void>::ConstPointer = nullptr) {
|
|
|
|
return (Pointer) ::new uchar[n * sizeof(_T)];
|
|
|
|
}
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
void deallocate(Pointer p, Size) { ::delete[] (uchar *) p; }
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U, typename ..._A>
|
|
|
|
void construct(_U *p, _A &&...args) {
|
|
|
|
::new((void *)p) _U(octa::forward<_A>(args)...);
|
|
|
|
}
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
void destroy(Pointer p) { p->~_T(); }
|
|
|
|
};
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _T> struct Allocator<const _T> {
|
|
|
|
typedef size_t Size;
|
|
|
|
typedef ptrdiff_t Difference;
|
|
|
|
typedef const _T Value;
|
|
|
|
typedef const _T &Reference;
|
|
|
|
typedef const _T &ConstReference;
|
|
|
|
typedef const _T *Pointer;
|
|
|
|
typedef const _T *ConstPointer;
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U> using Rebind = Allocator<_U>;
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
ConstPointer address(ConstReference v) const {
|
|
|
|
return address_of(v);
|
|
|
|
};
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
Size max_size() const { return Size(~0) / sizeof(_T); }
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
Pointer allocate(Size n, Allocator<void>::ConstPointer = nullptr) {
|
|
|
|
return (Pointer) ::new uchar[n * sizeof(_T)];
|
|
|
|
}
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
void deallocate(Pointer p, Size) { ::delete[] (uchar *) p; }
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U, typename ..._A>
|
|
|
|
void construct(_U *p, _A &&...args) {
|
|
|
|
::new((void *)p) _U(octa::forward<_A>(args)...);
|
|
|
|
}
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
void destroy(Pointer p) { p->~_T(); }
|
|
|
|
};
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _T, typename _U>
|
|
|
|
bool operator==(const Allocator<_T> &, const Allocator<_U> &) {
|
|
|
|
return true;
|
|
|
|
}
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _T, typename _U>
|
|
|
|
bool operator!=(const Allocator<_T> &, const Allocator<_U> &) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
/* allocator traits - modeled after libc++ */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct ConstPtrTest {
|
|
|
|
template<typename _U> static char test(
|
2015-06-03 18:52:20 +00:00
|
|
|
typename _U::ConstPointer * = 0);
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U> static int test(...);
|
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _T, typename _P, typename _A,
|
2015-06-04 00:56:04 +00:00
|
|
|
bool = ConstPtrTest<_A>::value>
|
|
|
|
struct ConstPointer {
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef typename _A::ConstPointer Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _T, typename _P, typename _A>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct ConstPointer<_T, _P, _A, false> {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef PointerRebind<_P, const _T> Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct VoidPtrTest {
|
|
|
|
template<typename _U> static char test(
|
2015-06-03 18:52:20 +00:00
|
|
|
typename _U::VoidPointer * = 0);
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U> static int test(...);
|
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _P, typename _A, bool = VoidPtrTest<_A>::value>
|
|
|
|
struct VoidPointer {
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef typename _A::VoidPointer Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _P, typename _A>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct VoidPointer<_P, _A, false> {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef PointerRebind<_P, void> Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct ConstVoidPtrTest {
|
|
|
|
template<typename _U> static char test(
|
2015-06-03 18:52:20 +00:00
|
|
|
typename _U::ConstVoidPointer * = 0);
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U> static int test(...);
|
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _P, typename _A, bool = ConstVoidPtrTest<_A>::value>
|
|
|
|
struct ConstVoidPointer {
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef typename _A::ConstVoidPointer Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _P, typename _A>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct ConstVoidPointer<_P, _A, false> {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef PointerRebind<_P, const void> Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct SizeTest {
|
|
|
|
template<typename _U> static char test(typename _U::Size * = 0);
|
|
|
|
template<typename _U> static int test(...);
|
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A, typename _D, bool = SizeTest<_A>::value>
|
|
|
|
struct SizeBase {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef octa::MakeUnsigned<_D> Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _A, typename _D>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct SizeBase<_A, _D, true> {
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef typename _A::Size Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
2015-06-04 00:56:04 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
/* allocator type traits */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using AllocatorType = _A;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using AllocatorValue = typename AllocatorType<_A>::Value;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
2015-06-04 01:09:07 +00:00
|
|
|
using AllocatorPointer = typename octa::detail::PointerType<
|
2015-06-04 00:56:04 +00:00
|
|
|
AllocatorValue<_A>, AllocatorType <_A>
|
|
|
|
>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using AllocatorConstPointer = typename octa::detail::ConstPointer<
|
|
|
|
AllocatorValue<_A>, AllocatorPointer<_A>, AllocatorType<_A>
|
|
|
|
>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using AllocatorVoidPointer = typename octa::detail::VoidPointer<
|
|
|
|
AllocatorPointer<_A>, AllocatorType<_A>
|
|
|
|
>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using AllocatorConstVoidPointer = typename octa::detail::ConstVoidPointer<
|
|
|
|
AllocatorPointer<_A>, AllocatorType<_A>
|
|
|
|
>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
/* allocator difference */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct DiffTest {
|
|
|
|
template<typename _U> static char test(typename _U::Difference * = 0);
|
|
|
|
template<typename _U> static int test(...);
|
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A, typename _P, bool = DiffTest<_A>::value>
|
|
|
|
struct AllocDifference {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef PointerDifference<_P> Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _A, typename _P>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct AllocDifference<_A, _P, true> {
|
2015-06-03 18:52:20 +00:00
|
|
|
typedef typename _A::Difference Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
2015-06-04 00:56:04 +00:00
|
|
|
}
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using AllocatorDifference = typename octa::detail::AllocDifference<
|
|
|
|
_A, AllocatorPointer<_A>
|
|
|
|
>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
/* allocator size */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using AllocatorSize = typename octa::detail::SizeBase<
|
|
|
|
_A, AllocatorDifference<_A>
|
|
|
|
>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
/* allocator rebind */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
namespace detail {
|
2015-06-04 01:20:20 +00:00
|
|
|
template<typename _T, typename _U, bool = octa::detail::HasRebind<_T, _U>::value>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct AllocTraitsRebindType {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef typename _T::template Rebind<_U> Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<template<typename, typename...> class _A, typename _T,
|
|
|
|
typename ..._Args, typename _U
|
|
|
|
>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct AllocTraitsRebindType<_A<_T, _Args...>, _U, true> {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef typename _A<_T, _Args...>::template Rebind<_U> Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<template<typename, typename...> class _A, typename _T,
|
|
|
|
typename ..._Args, typename _U
|
|
|
|
>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct AllocTraitsRebindType<_A<_T, _Args...>, _U, false> {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef _A<_U, _Args...> Type;
|
|
|
|
};
|
2015-06-04 00:56:04 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A, typename _T>
|
|
|
|
using AllocatorRebind = typename octa::detail::AllocTraitsRebindType<
|
|
|
|
AllocatorType<_A>, _T
|
|
|
|
>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
/* allocator propagate on container copy assignment */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct PropagateOnContainerCopyAssignmentTest {
|
|
|
|
template<typename _U> static char test(
|
2015-06-03 18:47:36 +00:00
|
|
|
typename _U::PropagateOnContainerCopyAssignment * = 0);
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U> static int test(...);
|
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A, bool = PropagateOnContainerCopyAssignmentTest<
|
2015-06-03 18:47:36 +00:00
|
|
|
_A
|
2015-06-04 00:56:04 +00:00
|
|
|
>::value> struct PropagateOnContainerCopyAssignmentBase {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef octa::False Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct PropagateOnContainerCopyAssignmentBase<_A, true> {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef typename _A::PropagateOnContainerCopyAssignment Type;
|
|
|
|
};
|
2015-06-04 00:56:04 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using PropagateOnContainerCopyAssignment
|
|
|
|
= typename octa::detail::PropagateOnContainerCopyAssignmentBase<_A>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
/* allocator propagate on container move assignment */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct PropagateOnContainerMoveAssignmentTest {
|
|
|
|
template<typename _U> static char test(
|
2015-06-03 18:47:36 +00:00
|
|
|
typename _U::PropagateOnContainerMoveAssignment * = 0);
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U> static int test(...);
|
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A, bool = PropagateOnContainerMoveAssignmentTest<
|
2015-06-03 18:47:36 +00:00
|
|
|
_A
|
2015-06-04 00:56:04 +00:00
|
|
|
>::value> struct PropagateOnContainerMoveAssignmentBase {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef octa::False Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct PropagateOnContainerMoveAssignmentBase<_A, true> {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef typename _A::PropagateOnContainerMoveAssignment Type;
|
|
|
|
};
|
2015-06-04 00:56:04 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using PropagateOnContainerMoveAssignment
|
|
|
|
= typename octa::detail::PropagateOnContainerMoveAssignmentBase<_A>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
/* allocator propagate on container swap */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct PropagateOnContainerSwapTest {
|
|
|
|
template<typename _U> static char test(
|
2015-06-03 18:47:36 +00:00
|
|
|
typename _U::PropagateOnContainerSwap * = 0);
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _U> static int test(...);
|
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A, bool = PropagateOnContainerSwapTest<_A>::value>
|
|
|
|
struct PropagateOnContainerSwapBase {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef octa::False Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct PropagateOnContainerSwapBase<_A, true> {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef typename _A::PropagateOnContainerSwap Type;
|
|
|
|
};
|
2015-06-04 00:56:04 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using PropagateOnContainerSwap
|
|
|
|
= typename octa::detail::PropagateOnContainerSwapBase<_A>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
/* allocator is always equal */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct IsAlwaysEqualTest {
|
|
|
|
template<typename _U> static char test(typename _U::IsAlwaysEqual * = 0);
|
|
|
|
template<typename _U> static int test(...);
|
|
|
|
static constexpr bool value = (sizeof(test<_T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A, bool = IsAlwaysEqualTest<_A>::value>
|
|
|
|
struct IsAlwaysEqualBase {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef typename octa::IsEmpty<_A>::Type Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct IsAlwaysEqualBase<_A, true> {
|
2015-06-03 18:47:36 +00:00
|
|
|
typedef typename _A::IsAlwaysEqual Type;
|
|
|
|
};
|
2015-06-04 00:56:04 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:56:04 +00:00
|
|
|
template<typename _A>
|
|
|
|
using IsAlwaysEqual = typename octa::detail::IsAlwaysEqualBase<_A>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
/* allocator allocate */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
template<typename _A>
|
|
|
|
inline AllocatorPointer<_A>
|
|
|
|
allocator_allocate(_A &a, AllocatorSize<_A> n) {
|
|
|
|
return a.allocate(n);
|
|
|
|
}
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _A, typename _S, typename _CVP>
|
2015-06-04 00:45:30 +00:00
|
|
|
auto allocate_hint_test(_A &&a, _S &&sz, _CVP &&p)
|
|
|
|
-> decltype(a.allocate(sz, p), octa::True());
|
2015-06-03 18:47:36 +00:00
|
|
|
|
|
|
|
template<typename _A, typename _S, typename _CVP>
|
2015-06-04 00:45:30 +00:00
|
|
|
auto allocate_hint_test(const _A &, _S &&, _CVP &&)
|
2015-06-03 18:47:36 +00:00
|
|
|
-> octa::False;
|
|
|
|
|
|
|
|
template<typename _A, typename _S, typename _CVP>
|
2015-06-04 00:45:30 +00:00
|
|
|
struct AllocateHintTest: octa::IntegralConstant<bool,
|
2015-06-03 18:47:36 +00:00
|
|
|
octa::IsSame<
|
2015-06-04 00:45:30 +00:00
|
|
|
decltype(allocate_hint_test(octa::declval<_A>(),
|
|
|
|
octa::declval<_S>(),
|
|
|
|
octa::declval<_CVP>())),
|
2015-06-03 18:47:36 +00:00
|
|
|
octa::True
|
|
|
|
>::value
|
|
|
|
> {};
|
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
inline AllocatorPointer<_A> allocate(_A &a, AllocatorSize<_A> n,
|
|
|
|
AllocatorConstVoidPointer<_A> h,
|
|
|
|
octa::True) {
|
|
|
|
return a.allocate(n, h);
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
inline AllocatorPointer<_A> allocate(_A &a, AllocatorSize<_A> n,
|
|
|
|
AllocatorConstVoidPointer<_A>,
|
|
|
|
octa::False) {
|
|
|
|
return a.allocate(n);
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
2015-06-04 00:45:30 +00:00
|
|
|
} /* namespace detail */
|
|
|
|
|
|
|
|
template<typename _A>
|
|
|
|
inline AllocatorPointer<_A>
|
|
|
|
allocator_allocate(_A &a, AllocatorSize<_A> n,
|
|
|
|
AllocatorConstVoidPointer<_A> h) {
|
|
|
|
return octa::detail::allocate(a, n, h,
|
|
|
|
octa::detail::AllocateHintTest<
|
2015-06-03 18:47:36 +00:00
|
|
|
_A, AllocatorSize<_A>, AllocatorConstVoidPointer<_A>
|
|
|
|
>());
|
2015-06-04 00:45:30 +00:00
|
|
|
}
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
/* allocator deallocate */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
template<typename _A>
|
|
|
|
inline void allocator_deallocate(_A &a, AllocatorPointer<_A> p,
|
|
|
|
AllocatorSize<_A> n) {
|
|
|
|
a.deallocate(p, n);
|
|
|
|
}
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
/* allocator construct */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _A, typename _T, typename ..._Args>
|
2015-06-04 00:45:30 +00:00
|
|
|
auto construct_test(_A &&a, _T *p, _Args &&...args)
|
|
|
|
-> decltype(a.construct(p, octa::forward<_Args>(args)...),
|
2015-06-03 18:47:36 +00:00
|
|
|
octa::True());
|
|
|
|
|
|
|
|
template<typename _A, typename _T, typename ..._Args>
|
2015-06-04 00:45:30 +00:00
|
|
|
auto construct_test(const _A &, _T *, _Args &&...)
|
2015-06-03 18:47:36 +00:00
|
|
|
-> octa::False;
|
|
|
|
|
|
|
|
template<typename _A, typename _T, typename ..._Args>
|
2015-06-04 00:45:30 +00:00
|
|
|
struct ConstructTest: octa::IntegralConstant<bool,
|
2015-06-03 18:47:36 +00:00
|
|
|
octa::IsSame<
|
2015-06-04 00:45:30 +00:00
|
|
|
decltype(construct_test(octa::declval<_A>(),
|
|
|
|
octa::declval<_T>(),
|
|
|
|
octa::declval<_Args>()...)),
|
2015-06-03 18:47:36 +00:00
|
|
|
octa::True
|
|
|
|
>::value
|
|
|
|
> {};
|
|
|
|
|
|
|
|
template<typename _A, typename _T, typename ..._Args>
|
2015-06-04 00:45:30 +00:00
|
|
|
inline void construct(octa::True, _A &a, _T *p, _Args &&...args) {
|
|
|
|
a.construct(p, octa::forward<_Args>(args)...);
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename _A, typename _T, typename ..._Args>
|
2015-06-04 00:45:30 +00:00
|
|
|
inline void construct(octa::False, _A &, _T *p, _Args &&...args) {
|
|
|
|
::new ((void *)p) _T(octa::forward<_Args>(args)...);
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
2015-06-04 00:45:30 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
template<typename _A, typename _T, typename ..._Args>
|
|
|
|
inline void allocator_construct(_A &a, _T *p, _Args &&...args) {
|
|
|
|
octa::detail::construct(octa::detail::ConstructTest<
|
|
|
|
_A, _T *, _Args...
|
|
|
|
>(), a, p, octa::forward<_Args>(args)...);
|
|
|
|
}
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
/* allocator destroy */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _A, typename _P>
|
2015-06-04 00:45:30 +00:00
|
|
|
auto destroy_test(_A &&a, _P &&p) -> decltype(a.destroy(p), octa::True());
|
2015-06-03 18:47:36 +00:00
|
|
|
|
|
|
|
template<typename _A, typename _P>
|
2015-06-04 00:45:30 +00:00
|
|
|
auto destroy_test(const _A &, _P &&) -> octa::False;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
|
|
|
template<typename _A, typename _P>
|
2015-06-04 00:45:30 +00:00
|
|
|
struct DestroyTest: octa::IntegralConstant<bool,
|
2015-06-03 18:47:36 +00:00
|
|
|
octa::IsSame<
|
2015-06-04 00:45:30 +00:00
|
|
|
decltype(destroy_test(octa::declval<_A>(), octa::declval<_P>())),
|
2015-06-03 18:47:36 +00:00
|
|
|
octa::True
|
|
|
|
>::value
|
|
|
|
> {};
|
|
|
|
|
|
|
|
template<typename _A, typename _T>
|
2015-06-04 00:45:30 +00:00
|
|
|
inline void destroy(octa::True, _A &a, _T *p) {
|
|
|
|
a.destroy(p);
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename _A, typename _T>
|
2015-06-04 00:45:30 +00:00
|
|
|
inline void destroy(octa::False, _A &, _T *p) {
|
|
|
|
p->~_T();
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
2015-06-04 00:45:30 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
template<typename _A, typename _T>
|
|
|
|
inline void allocator_destroy(_A &a, _T *p) {
|
|
|
|
octa::detail::destroy(octa::detail::DestroyTest<_A, _T *>(), a, p);
|
|
|
|
}
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
/* allocator max size */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
auto alloc_max_size_test(_A &&a) -> decltype(a.max_size(), octa::True());
|
2015-06-03 18:47:36 +00:00
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
auto alloc_max_size_test(const _A &) -> octa::False;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
struct AllocMaxSizeTest: octa::IntegralConstant<bool,
|
2015-06-03 18:47:36 +00:00
|
|
|
octa::IsSame<
|
2015-06-04 00:45:30 +00:00
|
|
|
decltype(alloc_max_size_test(octa::declval<_A &>())),
|
2015-06-03 18:47:36 +00:00
|
|
|
octa::True
|
|
|
|
>::value
|
|
|
|
> {};
|
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
inline AllocatorSize<_A> alloc_max_size(octa::True, const _A &a) {
|
|
|
|
return a.max_size();
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
inline AllocatorSize<_A> alloc_max_size(octa::False, const _A &) {
|
2015-06-03 18:47:36 +00:00
|
|
|
return AllocatorSize<_A>(~0);
|
|
|
|
}
|
2015-06-04 00:45:30 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
template<typename _A>
|
|
|
|
inline AllocatorSize<_A> allocator_max_size(const _A &a) {
|
|
|
|
return octa::detail::alloc_max_size(octa::detail::AllocMaxSizeTest<
|
|
|
|
const _A
|
|
|
|
>(), a);
|
|
|
|
}
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
/* allocator container copy */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
namespace detail {
|
2015-06-03 18:47:36 +00:00
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
auto alloc_copy_test(_A &&a) -> decltype(a.container_copy(), octa::True());
|
2015-06-03 18:47:36 +00:00
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
auto alloc_copy_test(const _A &) -> octa::False;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
struct AllocCopyTest: octa::IntegralConstant<bool,
|
2015-06-03 18:47:36 +00:00
|
|
|
octa::IsSame<
|
2015-06-04 00:45:30 +00:00
|
|
|
decltype(alloc_copy_test(octa::declval<_A &>())), octa::True
|
2015-06-03 18:47:36 +00:00
|
|
|
>::value
|
|
|
|
> {};
|
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
inline AllocatorType<_A> alloc_container_copy(octa::True, const _A &a) {
|
|
|
|
return a.container_copy();
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename _A>
|
2015-06-04 00:45:30 +00:00
|
|
|
inline AllocatorType<_A> alloc_container_copy(octa::False, const _A &a) {
|
|
|
|
return a;
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
2015-06-04 00:45:30 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
template<typename _A>
|
|
|
|
inline AllocatorType<_A> allocator_container_copy(const _A &a) {
|
|
|
|
return octa::detail::alloc_container_copy(octa::detail::AllocCopyTest<
|
|
|
|
const _A
|
|
|
|
>(), a);
|
|
|
|
}
|
2015-04-18 18:02:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|