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