From 749434f98c4342dd3f50b131701520ba7ec3c99f Mon Sep 17 00:00:00 2001 From: q66 Date: Wed, 3 Jun 2015 19:47:36 +0100 Subject: [PATCH] add allocator traits --- octa/memory.h | 458 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 455 insertions(+), 3 deletions(-) diff --git a/octa/memory.h b/octa/memory.h index dfeb99f..f6fa3ac 100644 --- a/octa/memory.h +++ b/octa/memory.h @@ -73,21 +73,21 @@ namespace octa { template static int __test(...); template - static char __test(typename _V::template rebind<_U> * = 0); + static char __test(typename _V::template Rebind<_U> * = 0); static constexpr bool value = (sizeof(__test<_T>(0)) == 1); }; template::value> struct __OctaPtrTraitsRebindType { - typedef typename _T::template rebind<_U> Type; + typedef typename _T::template Rebind<_U> Type; }; template class _T, typename _U, typename ..._A, typename _V > struct __OctaPtrTraitsRebindType<_T<_U, _A...>, _V, true> { - typedef typename _T<_U, _A...>::template rebind<_V> Type; + typedef typename _T<_U, _A...>::template Rebind<_V> Type; }; template class _T, typename _U, @@ -639,6 +639,458 @@ namespace octa { bool operator!=(const Allocator<_T> &, const Allocator<_U> &) { return false; } + + /* allocator traits - modeled after libc++ */ + + template + struct __OctaConstPtrTest { + template static char __test( + typename _U::ConstPtrType * = 0); + template static int __test(...); + static constexpr bool value = (sizeof(__test<_T>(0)) == 1); + }; + + template::value> + struct __OctaConstPtrType { + typedef typename _A::ConstPtrType Type; + }; + + template + struct __OctaConstPtrType<_T, _P, _A, false> { + typedef PointerRebind<_P, const _T> Type; + }; + + template + struct __OctaVoidPtrTest { + template static char __test( + typename _U::VoidPtrType * = 0); + template static int __test(...); + static constexpr bool value = (sizeof(__test<_T>(0)) == 1); + }; + + template::value> + struct __OctaVoidPtrType { + typedef typename _A::VoidPtrType Type; + }; + + template + struct __OctaVoidPtrType<_P, _A, false> { + typedef PointerRebind<_P, void> Type; + }; + + template + struct __OctaConstVoidPtrTest { + template static char __test( + typename _U::ConstVoidPtrType * = 0); + template static int __test(...); + static constexpr bool value = (sizeof(__test<_T>(0)) == 1); + }; + + template::value> + struct __OctaConstVoidPtrType { + typedef typename _A::ConstVoidPtrType Type; + }; + + template + struct __OctaConstVoidPtrType<_P, _A, false> { + typedef PointerRebind<_P, const void> Type; + }; + + template + struct __OctaSizeTest { + template static char __test(typename _U::SizeType * = 0); + template static int __test(...); + static constexpr bool value = (sizeof(__test<_T>(0)) == 1); + }; + + template::value> + struct __OctaSizeType { + typedef octa::MakeUnsigned<_D> Type; + }; + + template + struct __OctaSizeType<_A, _D, true> { + typedef typename _A::SizeType Type; + }; + + /* allocator type traits */ + + template + using AllocatorType = _A; + + template + using AllocatorValue = typename AllocatorType<_A>::ValType; + + template + using AllocatorPointer = typename __OctaPtrType< + AllocatorValue<_A>, AllocatorType <_A> + >::Type; + + template + using AllocatorConstPointer = typename __OctaConstPtrType< + AllocatorValue<_A>, AllocatorPointer<_A>, AllocatorType<_A> + >::Type; + + template + using AllocatorVoidPointer = typename __OctaVoidPtrType< + AllocatorPointer<_A>, AllocatorType<_A> + >::Type; + + template + using AllocatorConstVoidPointer = typename __OctaConstVoidPtrType< + AllocatorPointer<_A>, AllocatorType<_A> + >::Type; + + /* allocator difference */ + + template + struct __OctaDiffTest { + template static char __test(typename _U::DiffType * = 0); + template static int __test(...); + static constexpr bool value = (sizeof(__test<_T>(0)) == 1); + }; + + template::value> + struct __OctaAllocDiffType { + typedef PointerDifference<_P> Type; + }; + + template + struct __OctaAllocDiffType<_A, _P, true> { + typedef typename _A::DiffType Type; + }; + + template + using AllocatorDifference = typename __OctaAllocDiffType< + _A, AllocatorPointer<_A> + >::Type; + + /* allocator size */ + + template + using AllocatorSize = typename __OctaSizeType< + _A, AllocatorDifference<_A> + >::Type; + + /* allocator rebind */ + + template::value> + struct __OctaAllocTraitsRebindType { + typedef typename _T::template Rebind<_U> Type; + }; + + template class _A, typename _T, + typename ..._Args, typename _U + > + struct __OctaAllocTraitsRebindType<_A<_T, _Args...>, _U, true> { + typedef typename _A<_T, _Args...>::template Rebind<_U> Type; + }; + + template class _A, typename _T, + typename ..._Args, typename _U + > + struct __OctaAllocTraitsRebindType<_A<_T, _Args...>, _U, false> { + typedef _A<_U, _Args...> Type; + }; + + template + using AllocatorRebind = typename __OctaAllocTraitsRebindType< + AllocatorType<_A>, _T + >::Type; + + /* allocator propagate on container copy assignment */ + + template + struct __OctaPropagateOnContainerCopyAssignmentTest { + template static char __test( + typename _U::PropagateOnContainerCopyAssignment * = 0); + template static int __test(...); + static constexpr bool value = (sizeof(__test<_T>(0)) == 1); + }; + + template::value> struct __OctaPropagateOnContainerCopyAssignment { + typedef octa::False Type; + }; + + template + struct __OctaPropagateOnContainerCopyAssignment<_A, true> { + typedef typename _A::PropagateOnContainerCopyAssignment Type; + }; + + template + using PropagateOnContainerCopyAssignment + = typename __OctaPropagateOnContainerCopyAssignment<_A>::Type; + + /* allocator propagate on container move assignment */ + + template + struct __OctaPropagateOnContainerMoveAssignmentTest { + template static char __test( + typename _U::PropagateOnContainerMoveAssignment * = 0); + template static int __test(...); + static constexpr bool value = (sizeof(__test<_T>(0)) == 1); + }; + + template::value> struct __OctaPropagateOnContainerMoveAssignment { + typedef octa::False Type; + }; + + template + struct __OctaPropagateOnContainerMoveAssignment<_A, true> { + typedef typename _A::PropagateOnContainerMoveAssignment Type; + }; + + template + using PropagateOnContainerMoveAssignment + = typename __OctaPropagateOnContainerMoveAssignment<_A>::Type; + + /* allocator propagate on container swap */ + + template + struct __OctaPropagateOnContainerSwapTest { + template static char __test( + typename _U::PropagateOnContainerSwap * = 0); + template static int __test(...); + static constexpr bool value = (sizeof(__test<_T>(0)) == 1); + }; + + template::value> + struct __OctaPropagateOnContainerSwap { + typedef octa::False Type; + }; + + template + struct __OctaPropagateOnContainerSwap<_A, true> { + typedef typename _A::PropagateOnContainerSwap Type; + }; + + template + using PropagateOnContainerSwap + = typename __OctaPropagateOnContainerSwap<_A>::Type; + + /* allocator is always equal */ + + template + struct __OctaIsAlwaysEqualTest { + template static char __test( + typename _U::IsAlwaysEqual * = 0); + template static int __test(...); + static constexpr bool value = (sizeof(__test<_T>(0)) == 1); + }; + + template::value> + struct __OctaIsAlwaysEqual { + typedef typename octa::IsEmpty<_A>::Type Type; + }; + + template + struct __OctaIsAlwaysEqual<_A, true> { + typedef typename _A::IsAlwaysEqual Type; + }; + + template + using IsAlwaysEqual = typename __OctaIsAlwaysEqual<_A>::Type; + + /* allocator allocate */ + + template + inline AllocatorPointer<_A> + allocator_allocate(_A &__a, AllocatorSize<_A> __n) { + return __a.allocate(__n); + } + + template + auto __octa_allocate_hint_test(_A &&__a, _S &&__sz, _CVP &&__p) + -> decltype(__a.allocate(__sz, __p), octa::True()); + + template + auto __octa_allocate_hint_test(const _A &__a, _S &&__sz, _CVP &&__p) + -> octa::False; + + template + struct __OctaAllocateHintTest: octa::IntegralConstant(), + octa::declval<_S>(), + octa::declval<_CVP>())), + octa::True + >::value + > {}; + + template + inline AllocatorPointer<_A> + __octa_allocate(_A &__a, AllocatorSize<_A> __n, + AllocatorConstVoidPointer<_A> __h, octa::True) { + return __a.allocate(__n, __h); + } + + template + inline AllocatorPointer<_A> + __octa_allocate(_A &__a, AllocatorSize<_A> __n, + AllocatorConstVoidPointer<_A>, octa::False) { + return __a.allocate(__n); + } + + template + inline AllocatorPointer<_A> + allocator_allocate(_A &__a, AllocatorSize<_A> __n, + AllocatorConstVoidPointer<_A> __h) { + return __octa_allocate(__a, __n, __h, __OctaAllocateHintTest< + _A, AllocatorSize<_A>, AllocatorConstVoidPointer<_A> + >()); + } + + /* allocator deallocate */ + + template + inline void allocator_deallocate(_A &__a, AllocatorPointer<_A> __p, + AllocatorSize<_A> __n) { + __a.deallocate(__p, __n); + } + + /* allocator construct */ + + template + auto __octa_construct_test(_A &&__a, _T *__p, _Args &&...__args) + -> decltype(__a.construct(__p, octa::forward<_Args>(__args)...), + octa::True()); + + template + auto __octa_construct_test(const _A &__a, _T *__p, _Args &&...__args) + -> octa::False; + + template + struct __OctaConstructTest: octa::IntegralConstant(), + octa::declval<_T>(), + octa::declval<_Args>()...)), + octa::True + >::value + > {}; + + template + inline void + __octa_construct(octa::True, _A &__a, _T *__p, _Args &&...__args) { + __a.construct(__p, octa::forward<_Args>(__args)...); + } + + template + inline void + __octa_construct(octa::False, _A &, _T *__p, _Args &&...__args) { + ::new ((void *)__p) _T(octa::forward<_Args>(__args)...); + } + + template + inline void allocator_construct(_A &__a, _T *__p, _Args &&...__args) { + __octa_construct(__OctaConstructTest<_A, _T *, _Args...>(), + __a, __p, octa::forward<_Args>(__args)...); + } + + /* allocator destroy */ + + template + auto __octa_destroy_test(_A &&__a, _P &&__p) + -> decltype(__a.destroy(__p), octa::True()); + + template + auto __octa_destroy_test(const _A &__a, _P &&__p) -> octa::False; + + template + struct __OctaDestroyTest: octa::IntegralConstant(), + octa::declval<_P>())), + octa::True + >::value + > {}; + + template + inline void __octa_destroy(octa::True, _A &__a, _T *__p) { + __a.destroy(__p); + } + + template + inline void __octa_destroy(octa::False, _A &, _T *__p) { + __p->~_T(); + } + + template + inline void allocator_destroy(_A &__a, _T *__p) { + __octa_destroy(__OctaDestroyTest<_A, _T *>(), __a, __p); + } + + /* allocator max size */ + + template + auto __octa_alloc_max_size_test(_A &&__a) + -> decltype(__a.max_size(), octa::True()); + + template + auto __octa_alloc_max_size_test(const volatile _A &__a) -> octa::False; + + template + struct __OctaAllocMaxSizeTest: octa::IntegralConstant())), + octa::True + >::value + > {}; + + template + inline AllocatorSize<_A> __octa_alloc_max_size(octa::True, const _A &__a) { + return __a.max_size(); + } + + template + inline AllocatorSize<_A> __octa_alloc_max_size(octa::False, const _A &) { + return AllocatorSize<_A>(~0); + } + + template + inline AllocatorSize<_A> allocator_max_size(const _A &__a) { + return __octa_alloc_max_size(__OctaAllocMaxSizeTest(), __a); + } + + /* allocator container copy */ + + template + auto __octa_alloc_copy_test(_A &&__a) + -> decltype(__a.container_copy(), octa::True()); + + template + auto __octa_alloc_copy_test(const volatile _A &__a) -> octa::False; + + template + struct __OctaAllocCopyTest: octa::IntegralConstant())), + octa::True + >::value + > {}; + + template + inline AllocatorType<_A> + __octa_alloc_container_copy(octa::True, const _A &__a) { + return __a.container_copy(); + } + + template + inline AllocatorType<_A> + __octa_alloc_container_copy(octa::False, const _A &__a) { + return __a; + } + + template + inline AllocatorType<_A> allocator_container_copy(const _A &__a) { + return __octa_alloc_container_copy(__OctaAllocCopyTest(), + __a); + } } #endif \ No newline at end of file