1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_EXPERIMENTAL___MEMORY 11#define _LIBCPP_EXPERIMENTAL___MEMORY 12 13#include <__functional_base> 14#include <__memory/allocator_arg_t.h> 15#include <__memory/uses_allocator.h> 16#include <experimental/__config> 17#include <experimental/utility> // for erased_type 18#include <type_traits> 19 20#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 21#pragma GCC system_header 22#endif 23 24_LIBCPP_BEGIN_NAMESPACE_LFTS 25 26template < 27 class _Tp, class _Alloc 28 , bool = uses_allocator<_Tp, _Alloc>::value 29 , bool = __has_allocator_type<_Tp>::value 30 > 31struct __lfts_uses_allocator : public false_type {}; 32 33template <class _Tp, class _Alloc> 34struct __lfts_uses_allocator<_Tp, _Alloc, false, false> : public false_type {}; 35 36template <class _Tp, class _Alloc, bool HasAlloc> 37struct __lfts_uses_allocator<_Tp, _Alloc, true, HasAlloc> : public true_type {}; 38 39template <class _Tp, class _Alloc> 40struct __lfts_uses_allocator<_Tp, _Alloc, false, true> 41 : public integral_constant<bool 42 , is_convertible<_Alloc, typename _Tp::allocator_type>::value 43 || is_same<erased_type, typename _Tp::allocator_type>::value 44 > 45{}; 46 47template <bool _UsesAlloc, class _Tp, class _Alloc, class ..._Args> 48struct __lfts_uses_alloc_ctor_imp 49{ 50 static const int value = 0; 51}; 52 53template <class _Tp, class _Alloc, class ..._Args> 54struct __lfts_uses_alloc_ctor_imp<true, _Tp, _Alloc, _Args...> 55{ 56 static const bool __ic_first 57 = is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value; 58 59 static const bool __ic_second = 60 conditional< 61 __ic_first, 62 false_type, 63 is_constructible<_Tp, _Args..., _Alloc> 64 >::type::value; 65 66 static_assert(__ic_first || __ic_second, 67 "Request for uses allocator construction is ill-formed"); 68 69 static const int value = __ic_first ? 1 : 2; 70}; 71 72template <class _Tp, class _Alloc, class ..._Args> 73struct __lfts_uses_alloc_ctor 74 : integral_constant<int, 75 __lfts_uses_alloc_ctor_imp< 76 __lfts_uses_allocator<_Tp, _Alloc>::value 77 , _Tp, _Alloc, _Args... 78 >::value 79 > 80{}; 81 82template <class _Tp, class _Allocator, class... _Args> 83inline _LIBCPP_INLINE_VISIBILITY 84void __user_alloc_construct_impl (integral_constant<int, 0>, _Tp *__storage, const _Allocator &, _Args &&... __args ) 85{ 86 new (__storage) _Tp (_VSTD::forward<_Args>(__args)...); 87} 88 89// FIXME: This should have a version which takes a non-const alloc. 90template <class _Tp, class _Allocator, class... _Args> 91inline _LIBCPP_INLINE_VISIBILITY 92void __user_alloc_construct_impl (integral_constant<int, 1>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) 93{ 94 new (__storage) _Tp (allocator_arg, __a, _VSTD::forward<_Args>(__args)...); 95} 96 97// FIXME: This should have a version which takes a non-const alloc. 98template <class _Tp, class _Allocator, class... _Args> 99inline _LIBCPP_INLINE_VISIBILITY 100void __user_alloc_construct_impl (integral_constant<int, 2>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) 101{ 102 new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a); 103} 104 105template <class _Tp, class _Alloc, class ..._Args> 106inline _LIBCPP_INLINE_VISIBILITY 107void __lfts_user_alloc_construct( 108 _Tp * __store, const _Alloc & __a, _Args &&... __args) 109{ 110 ::std::experimental::fundamentals_v1::__user_alloc_construct_impl( 111 typename __lfts_uses_alloc_ctor<_Tp, _Alloc, _Args...>::type() 112 , __store, __a, _VSTD::forward<_Args>(__args)... 113 ); 114} 115 116_LIBCPP_END_NAMESPACE_LFTS 117 118#endif /* _LIBCPP_EXPERIMENTAL___MEMORY */ 119