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