2015-04-18 18:02:44 +00:00
|
|
|
/* Memory utilities for OctaSTD.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#ifndef OSTD_MEMORY_HH
|
|
|
|
#define OSTD_MEMORY_HH
|
2015-04-18 18:02:44 +00:00
|
|
|
|
2015-05-13 19:56:36 +00:00
|
|
|
#include <stddef.h>
|
2017-01-14 14:09:27 +00:00
|
|
|
#include <new>
|
2017-01-29 14:16:13 +00:00
|
|
|
#include <memory>
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#include "ostd/utility.hh"
|
|
|
|
#include "ostd/type_traits.hh"
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
namespace ostd {
|
2015-06-04 01:20:20 +00:00
|
|
|
/* address of */
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2016-09-11 18:46:34 +00:00
|
|
|
template<typename T> constexpr T *address_of(T &v) noexcept {
|
2016-07-31 19:40:25 +00:00
|
|
|
return reinterpret_cast<T *>(
|
|
|
|
&const_cast<char &>(reinterpret_cast<char const volatile &>(v))
|
|
|
|
);
|
2015-06-04 01:20:20 +00:00
|
|
|
}
|
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-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct HasElement {
|
2016-07-31 19:40:25 +00:00
|
|
|
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 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, bool = HasElement<T>::value>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerElementBase;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
struct PointerElementBase<T, true> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename T::Element;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<template<typename, typename...> class T, typename U, typename ...A>
|
|
|
|
struct PointerElementBase<T<U, A...>, true> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename T<U, A...>::Element;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<template<typename, typename...> class T, typename U, typename ...A>
|
|
|
|
struct PointerElementBase<T<U, A...>, false> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = U;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerElementType {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename PointerElementBase<T>::Type;
|
2015-06-04 01:20:20 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct PointerElementType<T *> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = T;
|
2015-06-04 01:20:20 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct HasDifference {
|
2016-07-31 19:40:25 +00:00
|
|
|
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 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, bool = HasDifference<T>::value>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerDifferenceBase {
|
2015-07-05 22:59:36 +00:00
|
|
|
using Type = Ptrdiff;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
struct PointerDifferenceBase<T, true> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename T::Difference;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerDifferenceType {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename PointerDifferenceBase<T>::Type;
|
2015-06-04 01:20:20 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct PointerDifferenceType<T *> {
|
2015-07-05 22:59:36 +00:00
|
|
|
using Type = Ptrdiff;
|
2015-06-04 01:20:20 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct HasRebind {
|
2016-07-31 19:40:25 +00:00
|
|
|
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 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U, bool = HasRebind<T, U>::value>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerRebindBase {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename T::template Rebind<U>;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<
|
|
|
|
template<typename, typename...> class T, typename U,
|
2015-06-04 21:57:06 +00:00
|
|
|
typename ...A, typename V
|
2015-04-27 17:56:17 +00:00
|
|
|
>
|
2015-06-04 21:57:06 +00:00
|
|
|
struct PointerRebindBase<T<U, A...>, V, true> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename T<U, A...>::template Rebind<V>;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<
|
|
|
|
template<typename, typename...> class T, typename U,
|
2015-06-04 21:57:06 +00:00
|
|
|
typename ...A, typename V
|
2015-04-27 17:56:17 +00:00
|
|
|
>
|
2015-06-04 21:57:06 +00:00
|
|
|
struct PointerRebindBase<T<U, A...>, V, false> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = T<V, A...>;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerRebindType {
|
2016-09-18 17:22:54 +00:00
|
|
|
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 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
|
|
|
struct PointerRebindType<T *, U> {
|
2016-09-18 17:22:54 +00:00
|
|
|
using Type = U *;
|
2015-05-03 21:39:32 +00:00
|
|
|
};
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerPointer {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = T;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct PointerPointer<T *> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = T *;
|
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 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using Pointer = typename detail::PointerPointer<T>::Type;
|
2015-05-03 21:39:32 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using PointerElement = typename detail::PointerElementType<T>::Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using PointerDifference = typename detail::PointerDifferenceType<T>::Type;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
2015-07-05 22:59:36 +00:00
|
|
|
using PointerRebind = typename 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-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 01:20:20 +00:00
|
|
|
struct PointerTo {
|
2016-07-31 19:40:25 +00:00
|
|
|
static T pointer_to(
|
|
|
|
Conditional<
|
|
|
|
IsVoid<PointerElement<T>>, PointerToNat, PointerElement<T>
|
|
|
|
> &r
|
|
|
|
) {
|
2015-06-04 21:57:06 +00:00
|
|
|
return T::pointer_to(r);
|
2015-05-03 21:39:32 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
struct PointerTo<T *> {
|
2016-01-12 21:45:26 +00:00
|
|
|
static T pointer_to(Conditional<IsVoid<T>, PointerToNat, T> &r) {
|
2015-07-05 22:59:36 +00:00
|
|
|
return 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 21:57:06 +00:00
|
|
|
template<typename T>
|
2016-07-31 19:40:25 +00:00
|
|
|
static T pointer_to(
|
|
|
|
Conditional<
|
|
|
|
IsVoid<PointerElement<T>>, detail::PointerToNat, PointerElement<T>
|
|
|
|
> &r
|
|
|
|
) {
|
2015-07-05 22:59:36 +00:00
|
|
|
return detail::PointerTo<T>::pointer_to(r);
|
2015-06-04 01:20:20 +00:00
|
|
|
}
|
2015-05-03 21:39:32 +00:00
|
|
|
|
2015-06-04 01:09:07 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 01:09:07 +00:00
|
|
|
static int ptr_test(...);
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
|
|
|
static char ptr_test(typename T::Pointer * = 0);
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
constexpr bool HasPtr = sizeof(ptr_test<T>(0)) == 1;
|
2015-04-27 17:56:17 +00:00
|
|
|
|
2016-01-20 18:09:44 +00:00
|
|
|
template<typename T, typename D, bool = HasPtr<D>>
|
2015-06-04 01:09:07 +00:00
|
|
|
struct PointerBase {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename D::Pointer;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T, typename D>
|
|
|
|
struct PointerBase<T, D, false> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = T *;
|
2015-04-27 17:56:17 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T, typename D>
|
|
|
|
struct PointerType {
|
2015-07-05 22:59:36 +00:00
|
|
|
using Type = typename PointerBase<T, RemoveReference<D>>::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 00:56:04 +00:00
|
|
|
/* allocator */
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
struct Allocator {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Value = T;
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2016-09-11 18:46:34 +00:00
|
|
|
Allocator() noexcept {}
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename U>
|
2016-09-11 18:46:34 +00:00
|
|
|
Allocator(Allocator<U> const &) noexcept {}
|
2015-06-14 01:36:20 +00:00
|
|
|
|
2016-09-18 17:22:54 +00:00
|
|
|
Value *allocate(Size n) {
|
|
|
|
return reinterpret_cast<Value *>(::new byte[n * sizeof(T)]);
|
2015-06-04 00:56:04 +00:00
|
|
|
}
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2016-09-18 17:22:54 +00:00
|
|
|
void deallocate(Value *p, Size) noexcept {
|
2016-09-11 18:46:34 +00:00
|
|
|
::delete[] reinterpret_cast<byte *>(p);
|
|
|
|
}
|
2015-06-04 00:56:04 +00:00
|
|
|
};
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
2016-09-11 18:46:34 +00:00
|
|
|
bool operator==(Allocator<T> const &, Allocator<U> const &) noexcept {
|
2015-06-04 00:56:04 +00:00
|
|
|
return true;
|
|
|
|
}
|
2015-05-13 19:56:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename U>
|
2016-09-11 18:46:34 +00:00
|
|
|
bool operator!=(Allocator<T> const &, Allocator<U> const &) noexcept {
|
2015-06-04 00:56:04 +00:00
|
|
|
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-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct ConstPtrTest {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename U>
|
|
|
|
static char test(typename U::ConstPointer * = 0);
|
|
|
|
template<typename U>
|
|
|
|
static int test(...);
|
2015-06-04 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T, typename P, typename A, bool = ConstPtrTest<A>::value>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct ConstPointer {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename A::ConstPointer;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T, typename P, typename A>
|
|
|
|
struct ConstPointer<T, P, A, false> {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = PointerRebind<P, T const>;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct VoidPtrTest {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename U>
|
|
|
|
static char test(typename U::VoidPointer * = 0);
|
|
|
|
template<typename U>
|
|
|
|
static int test(...);
|
2015-06-04 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename P, typename A, bool = VoidPtrTest<A>::value>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct VoidPointer {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename A::VoidPointer;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename P, typename A>
|
|
|
|
struct VoidPointer<P, A, false> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = PointerRebind<P, void>;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct ConstVoidPtrTest {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename U> static char test(
|
|
|
|
typename U::ConstVoidPointer * = 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 21:57:06 +00:00
|
|
|
template<typename P, typename A, bool = ConstVoidPtrTest<A>::value>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct ConstVoidPointer {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename A::ConstVoidPointer;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename P, typename A>
|
|
|
|
struct ConstVoidPointer<P, A, false> {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Type = PointerRebind<P, void const>;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct SizeTest {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename U>
|
|
|
|
static char test(typename U::Size * = 0);
|
|
|
|
template<typename U>
|
|
|
|
static int test(...);
|
2015-06-04 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename D, bool = SizeTest<A>::value>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct SizeBase {
|
2015-07-05 22:59:36 +00:00
|
|
|
using Type = MakeUnsigned<D>;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename D>
|
|
|
|
struct SizeBase<A, D, true> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename A::Size;
|
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 21:57:06 +00:00
|
|
|
template<typename A>
|
|
|
|
using AllocatorType = A;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
|
|
|
using AllocatorValue = typename AllocatorType<A>::Value;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AllocatorPointer = typename detail::PointerType<
|
2015-06-10 23:08:56 +00:00
|
|
|
AllocatorValue<A>, AllocatorType<A>
|
2015-06-04 00:56:04 +00:00
|
|
|
>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AllocatorConstPointer = typename detail::ConstPointer<
|
2015-06-04 21:57:06 +00:00
|
|
|
AllocatorValue<A>, AllocatorPointer<A>, AllocatorType<A>
|
2015-06-04 00:56:04 +00:00
|
|
|
>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AllocatorVoidPointer = typename detail::VoidPointer<
|
2015-06-04 21:57:06 +00:00
|
|
|
AllocatorPointer<A>, AllocatorType<A>
|
2015-06-04 00:56:04 +00:00
|
|
|
>::Type;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AllocatorConstVoidPointer = typename detail::ConstVoidPointer<
|
2015-06-04 21:57:06 +00:00
|
|
|
AllocatorPointer<A>, AllocatorType<A>
|
2015-06-04 00:56:04 +00:00
|
|
|
>::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-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct DiffTest {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename U>
|
|
|
|
static char test(typename U::Difference * = 0);
|
|
|
|
template<typename U>
|
|
|
|
static int test(...);
|
2015-06-04 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename P, bool = DiffTest<A>::value>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct AllocDifference {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = PointerDifference<P>;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename P>
|
|
|
|
struct AllocDifference<A, P, true> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename A::Difference;
|
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 21:57:06 +00:00
|
|
|
template<typename A>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AllocatorDifference = typename detail::AllocDifference<
|
2015-06-04 21:57:06 +00:00
|
|
|
A, AllocatorPointer<A>
|
2015-06-04 00:56:04 +00:00
|
|
|
>::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 21:57:06 +00:00
|
|
|
template<typename A>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AllocatorSize = typename detail::SizeBase<
|
2015-06-04 21:57:06 +00:00
|
|
|
A, AllocatorDifference<A>
|
2015-06-04 00:56:04 +00:00
|
|
|
>::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-07-05 22:59:36 +00:00
|
|
|
template<typename T, typename U, bool = detail::HasRebind<T, U>::value>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct AllocTraitsRebindType {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename T::template Rebind<U>;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<
|
|
|
|
template<typename, typename...> class A, typename T,
|
2015-06-04 21:57:06 +00:00
|
|
|
typename ...Args, typename U
|
2015-06-03 18:47:36 +00:00
|
|
|
>
|
2015-06-04 21:57:06 +00:00
|
|
|
struct AllocTraitsRebindType<A<T, Args...>, U, true> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = typename A<T, Args...>::template Rebind<U>;
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<
|
|
|
|
template<typename, typename...> class A, typename T,
|
2015-06-04 21:57:06 +00:00
|
|
|
typename ...Args, typename U
|
2015-06-03 18:47:36 +00:00
|
|
|
>
|
2015-06-04 21:57:06 +00:00
|
|
|
struct AllocTraitsRebindType<A<T, Args...>, U, false> {
|
2015-06-07 23:55:08 +00:00
|
|
|
using Type = A<U, Args...>;
|
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 21:57:06 +00:00
|
|
|
template<typename A, typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
using AllocatorRebind = typename detail::AllocTraitsRebindType<
|
2015-06-04 21:57:06 +00:00
|
|
|
AllocatorType<A>, T
|
2015-06-04 00:56:04 +00:00
|
|
|
>::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-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct PropagateOnContainerCopyAssignmentTest {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename U>
|
|
|
|
static char test(decltype(U::PropagateOnContainerCopyAssignment) * = 0);
|
|
|
|
template<typename U>
|
|
|
|
static int test(...);
|
2015-06-04 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename A, bool =
|
|
|
|
PropagateOnContainerCopyAssignmentTest<A>::value
|
|
|
|
>
|
|
|
|
constexpr bool PropagateOnContainerCopyAssignmentBase = false;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool PropagateOnContainerCopyAssignmentBase<A, true> =
|
|
|
|
A::PropagateOnContainerCopyAssignment;
|
2015-06-04 00:56:04 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool AllocatorPropagateOnContainerCopyAssignment =
|
|
|
|
detail::PropagateOnContainerCopyAssignmentBase<A>;
|
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-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct PropagateOnContainerMoveAssignmentTest {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename U>
|
|
|
|
static char test(decltype(U::PropagateOnContainerMoveAssignment) * = 0);
|
|
|
|
template<typename U>
|
|
|
|
static int test(...);
|
2015-06-04 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename A, bool =
|
|
|
|
PropagateOnContainerMoveAssignmentTest<A>::value
|
|
|
|
>
|
|
|
|
constexpr bool PropagateOnContainerMoveAssignmentBase = false;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool PropagateOnContainerMoveAssignmentBase<A, true> =
|
|
|
|
A::PropagateOnContainerMoveAssignment;
|
2015-06-04 00:56:04 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool AllocatorPropagateOnContainerMoveAssignment =
|
|
|
|
detail::PropagateOnContainerMoveAssignmentBase<A>;
|
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-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct PropagateOnContainerSwapTest {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename U>
|
|
|
|
static char test(decltype(U::PropagateOnContainerSwap) * = 0);
|
|
|
|
template<typename U>
|
|
|
|
static int test(...);
|
2015-06-04 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, bool = PropagateOnContainerSwapTest<A>::value>
|
2016-01-20 19:05:11 +00:00
|
|
|
constexpr bool PropagateOnContainerSwapBase = false;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool PropagateOnContainerSwapBase<A, true> =
|
|
|
|
A::PropagateOnContainerSwap;
|
2015-06-04 00:56:04 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool AllocatorPropagateOnContainerSwap =
|
|
|
|
detail::PropagateOnContainerSwapBase<A>;
|
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-04 21:57:06 +00:00
|
|
|
template<typename T>
|
2015-06-04 00:56:04 +00:00
|
|
|
struct IsAlwaysEqualTest {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename U>
|
|
|
|
static char test(decltype(U::IsAlwaysEqual) * = 0);
|
|
|
|
template<typename U>
|
|
|
|
static int test(...);
|
2015-06-04 21:57:06 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
2015-06-03 18:47:36 +00:00
|
|
|
};
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, bool = IsAlwaysEqualTest<A>::value>
|
2016-01-20 19:05:11 +00:00
|
|
|
constexpr bool IsAlwaysEqualBase = IsEmpty<A>;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-01-20 19:05:11 +00:00
|
|
|
constexpr bool IsAlwaysEqualBase<A, true> = A::IsAlwaysEqual;
|
2015-06-04 00:56:04 +00:00
|
|
|
} /* namespace detail */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-01-20 19:05:11 +00:00
|
|
|
constexpr bool AllocatorIsAlwaysEqual = detail::IsAlwaysEqualBase<A>;
|
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 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
inline AllocatorPointer<A> allocator_allocate(A &a, AllocatorSize<A> n) {
|
2015-06-04 00:45:30 +00:00
|
|
|
return a.allocate(n);
|
|
|
|
}
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename S, typename CVP>
|
2016-07-31 19:40:25 +00:00
|
|
|
auto allocate_hint_test(A &&a, S &&sz, CVP &&p) ->
|
|
|
|
decltype(a.allocate(sz, p), True());
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename S, typename CVP>
|
2016-07-31 19:40:25 +00:00
|
|
|
auto allocate_hint_test(A const &, S &&, CVP &&) -> False;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename S, typename CVP>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool AllocateHintTest =
|
|
|
|
IsSame<
|
|
|
|
decltype(allocate_hint_test(
|
2017-01-29 14:29:11 +00:00
|
|
|
std::declval<A>(), std::declval<S>(), std::declval<CVP>()
|
2016-07-31 19:40:25 +00:00
|
|
|
)), True
|
2016-01-20 19:05:11 +00:00
|
|
|
>;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
inline AllocatorPointer<A> allocate(
|
|
|
|
A &a, AllocatorSize<A> n, AllocatorConstVoidPointer<A> h, True
|
|
|
|
) {
|
2015-06-04 00:45:30 +00:00
|
|
|
return a.allocate(n, h);
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
inline AllocatorPointer<A> allocate(
|
|
|
|
A &a, AllocatorSize<A> n, AllocatorConstVoidPointer<A>, False
|
|
|
|
) {
|
2015-06-04 00:45:30 +00:00
|
|
|
return a.allocate(n);
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
2015-06-04 00:45:30 +00:00
|
|
|
} /* namespace detail */
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
inline AllocatorPointer<A> allocator_allocate(
|
|
|
|
A &a, AllocatorSize<A> n, AllocatorConstVoidPointer<A> h
|
|
|
|
) {
|
|
|
|
return detail::allocate(
|
|
|
|
a, n, h, BoolConstant<detail::AllocateHintTest<
|
2015-06-04 21:57:06 +00:00
|
|
|
A, AllocatorSize<A>, AllocatorConstVoidPointer<A>
|
2016-07-31 19:40:25 +00:00
|
|
|
>>()
|
|
|
|
);
|
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 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
inline void allocator_deallocate(
|
|
|
|
A &a, AllocatorPointer<A> p, AllocatorSize<A> n
|
2016-09-11 18:46:34 +00:00
|
|
|
) noexcept {
|
2015-06-04 00:45:30 +00:00
|
|
|
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-04 21:57:06 +00:00
|
|
|
template<typename A, typename T, typename ...Args>
|
2016-07-31 19:40:25 +00:00
|
|
|
auto construct_test(A &&a, T *p, Args &&...args) ->
|
2017-01-25 00:44:22 +00:00
|
|
|
decltype(a.construct(p, std::forward<Args>(args)...), True());
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename T, typename ...Args>
|
2016-07-31 19:40:25 +00:00
|
|
|
auto construct_test(A const &, T *, Args &&...) -> False;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename T, typename ...Args>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool ConstructTest =
|
|
|
|
IsSame<
|
|
|
|
decltype(construct_test(
|
2017-01-29 14:29:11 +00:00
|
|
|
std::declval<A>(), std::declval<T>(), std::declval<Args>()...
|
2016-07-31 19:40:25 +00:00
|
|
|
)), True
|
2016-01-20 19:05:11 +00:00
|
|
|
>;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename T, typename ...Args>
|
2015-07-05 22:59:36 +00:00
|
|
|
inline void construct(True, A &a, T *p, Args &&...args) {
|
2017-01-25 00:44:22 +00:00
|
|
|
a.construct(p, std::forward<Args>(args)...);
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename T, typename ...Args>
|
2015-07-05 22:59:36 +00:00
|
|
|
inline void construct(False, A &, T *p, Args &&...args) {
|
2017-01-25 00:44:22 +00:00
|
|
|
::new (p) T(std::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 21:57:06 +00:00
|
|
|
template<typename A, typename T, typename ...Args>
|
|
|
|
inline void allocator_construct(A &a, T *p, Args &&...args) {
|
2016-07-31 19:40:25 +00:00
|
|
|
detail::construct(
|
|
|
|
BoolConstant<detail::ConstructTest<A, T *, Args...>>(),
|
2017-01-25 00:44:22 +00:00
|
|
|
a, p, std::forward<Args>(args)...
|
2016-07-31 19:40:25 +00:00
|
|
|
);
|
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 destroy */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename P>
|
2015-07-05 22:59:36 +00:00
|
|
|
auto destroy_test(A &&a, P &&p) -> decltype(a.destroy(p), True());
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename P>
|
2016-06-23 18:18:35 +00:00
|
|
|
auto destroy_test(A const &, P &&) -> False;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename P>
|
2017-01-29 14:29:11 +00:00
|
|
|
constexpr bool DestroyTest = IsSame<
|
|
|
|
decltype(destroy_test(std::declval<A>(), std::declval<P>())), True
|
|
|
|
>;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
inline void destroy(True, A &a, T *p) {
|
2015-06-04 00:45:30 +00:00
|
|
|
a.destroy(p);
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A, typename T>
|
2015-07-05 22:59:36 +00:00
|
|
|
inline void destroy(False, A &, T *p) {
|
2015-06-04 21:57:06 +00:00
|
|
|
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 21:57:06 +00:00
|
|
|
template<typename A, typename T>
|
2016-09-11 18:46:34 +00:00
|
|
|
inline void allocator_destroy(A &a, T *p) noexcept {
|
2016-01-20 19:05:11 +00:00
|
|
|
detail::destroy(BoolConstant<detail::DestroyTest<A, T *>>(), a, p);
|
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 max size */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2015-07-05 22:59:36 +00:00
|
|
|
auto alloc_max_size_test(A &&a) -> decltype(a.max_size(), True());
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
auto alloc_max_size_test(A const &) -> False;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool AllocMaxSizeTest =
|
2017-01-29 14:29:11 +00:00
|
|
|
IsSame<decltype(alloc_max_size_test(std::declval<A &>())), True>;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline AllocatorSize<A> alloc_max_size(True, A const &a) {
|
2015-06-04 00:45:30 +00:00
|
|
|
return a.max_size();
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline AllocatorSize<A> alloc_max_size(False, A const &) {
|
2015-06-04 21:57:06 +00:00
|
|
|
return AllocatorSize<A>(~0);
|
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 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-09-11 18:46:34 +00:00
|
|
|
inline AllocatorSize<A> allocator_max_size(A const &a) noexcept {
|
2016-07-31 19:40:25 +00:00
|
|
|
return detail::alloc_max_size(
|
|
|
|
BoolConstant<detail::AllocMaxSizeTest<A const>>(), 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 container copy */
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 00:45:30 +00:00
|
|
|
namespace detail {
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2015-07-05 22:59:36 +00:00
|
|
|
auto alloc_copy_test(A &&a) -> decltype(a.container_copy(), True());
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
auto alloc_copy_test(A const &) -> False;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr bool AllocCopyTest =
|
2017-01-29 14:29:11 +00:00
|
|
|
IsSame<decltype(alloc_copy_test(std::declval<A &>())), True>;
|
2015-06-03 18:47:36 +00:00
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline AllocatorType<A> alloc_container_copy(True, A const &a) {
|
2015-06-04 00:45:30 +00:00
|
|
|
return a.container_copy();
|
2015-06-03 18:47:36 +00:00
|
|
|
}
|
|
|
|
|
2015-06-04 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline AllocatorType<A> alloc_container_copy(False, A const &a) {
|
2015-06-04 00:45:30 +00:00
|
|
|
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 21:57:06 +00:00
|
|
|
template<typename A>
|
2016-06-23 18:18:35 +00:00
|
|
|
inline AllocatorType<A> allocator_container_copy(A const &a) {
|
2016-07-31 19:40:25 +00:00
|
|
|
return detail::alloc_container_copy(
|
|
|
|
BoolConstant<detail::AllocCopyTest<A const>>(), a
|
|
|
|
);
|
2015-06-04 00:45:30 +00:00
|
|
|
}
|
2015-06-07 00:14:04 +00:00
|
|
|
|
2015-07-10 22:50:01 +00:00
|
|
|
/* allocator arg */
|
|
|
|
|
2015-06-07 00:14:04 +00:00
|
|
|
struct AllocatorArg {};
|
|
|
|
|
|
|
|
constexpr AllocatorArg allocator_arg = AllocatorArg();
|
|
|
|
|
2015-07-10 22:50:01 +00:00
|
|
|
/* uses allocator */
|
|
|
|
|
|
|
|
namespace detail {
|
2016-07-31 19:40:25 +00:00
|
|
|
template<typename T>
|
|
|
|
struct HasAllocatorType {
|
|
|
|
template<typename U>
|
|
|
|
static char test(typename U::Allocator *);
|
|
|
|
template<typename U>
|
|
|
|
static int test(...);
|
2015-07-10 22:50:01 +00:00
|
|
|
static constexpr bool value = (sizeof(test<T>(0)) == 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename A, bool = HasAllocatorType<T>::value>
|
2016-01-20 18:42:29 +00:00
|
|
|
constexpr bool UsesAllocatorBase = IsConvertible<A, typename T::Allocator>;
|
2015-07-10 22:50:01 +00:00
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-01-20 18:42:29 +00:00
|
|
|
constexpr bool UsesAllocatorBase<T, A, false> = false;
|
2015-07-10 22:50:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename A>
|
2016-01-20 18:42:29 +00:00
|
|
|
constexpr bool UsesAllocator = detail::UsesAllocatorBase<T, A>;
|
2015-07-10 22:50:01 +00:00
|
|
|
|
|
|
|
/* uses allocator ctor */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename T, typename A, typename ...Args>
|
|
|
|
struct UsesAllocCtor {
|
2016-01-20 18:42:29 +00:00
|
|
|
static constexpr bool ua = UsesAllocator<T, A>;
|
2015-07-10 22:50:01 +00:00
|
|
|
static constexpr bool ic = IsConstructible<
|
|
|
|
T, AllocatorArg, A, Args...
|
2016-01-12 22:09:40 +00:00
|
|
|
>;
|
2015-07-10 22:50:01 +00:00
|
|
|
static constexpr int value = ua ? (2 - ic) : 0;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename A, typename ...Args>
|
2016-07-31 19:40:25 +00:00
|
|
|
constexpr int UsesAllocatorConstructor =
|
|
|
|
detail::UsesAllocCtor<T, A, Args...>::value;
|
2015-07-10 22:50:01 +00:00
|
|
|
|
2016-09-11 14:26:36 +00:00
|
|
|
/* util for other classes */
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename A>
|
2017-01-09 16:58:28 +00:00
|
|
|
struct AllocatorDestructor {
|
2016-09-11 15:58:16 +00:00
|
|
|
using Pointer = AllocatorPointer<A>;
|
|
|
|
using Size = ostd::Size;
|
2016-09-11 14:26:36 +00:00
|
|
|
AllocatorDestructor(A &a, Size s) noexcept: p_alloc(a), p_size(s) {}
|
2016-09-11 15:58:16 +00:00
|
|
|
void operator()(Pointer p) noexcept {
|
2016-09-11 14:26:36 +00:00
|
|
|
allocator_deallocate(p_alloc, p, p_size);
|
|
|
|
}
|
2017-01-09 16:58:28 +00:00
|
|
|
private:
|
|
|
|
A &p_alloc;
|
|
|
|
Size p_size;
|
2016-09-11 14:26:36 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
} /* namespace ostd */
|
2015-04-18 18:02:44 +00:00
|
|
|
|
2016-02-07 21:17:15 +00:00
|
|
|
#endif
|