115551efdSEric Fiselier// -*- C++ -*- 215551efdSEric Fiselier//===----------------------------------------------------------------------===// 315551efdSEric Fiselier// 457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information. 657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 715551efdSEric Fiselier// 815551efdSEric Fiselier//===----------------------------------------------------------------------===// 915551efdSEric Fiselier 1015551efdSEric Fiselier#ifndef _LIBCPP_EXPERIMENTAL___MEMORY 1115551efdSEric Fiselier#define _LIBCPP_EXPERIMENTAL___MEMORY 1215551efdSEric Fiselier 13050b064fSChristopher Di Bella#include <__memory/allocator_arg_t.h> 14050b064fSChristopher Di Bella#include <__memory/uses_allocator.h> 1515551efdSEric Fiselier#include <experimental/__config> 1615551efdSEric Fiselier#include <experimental/utility> // for erased_type 1715551efdSEric Fiselier#include <type_traits> 1815551efdSEric Fiselier 19*413c3c4fSArthur O'Dwyer#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20*413c3c4fSArthur O'Dwyer# pragma GCC system_header 21*413c3c4fSArthur O'Dwyer#endif 22*413c3c4fSArthur O'Dwyer 2315551efdSEric Fiselier_LIBCPP_BEGIN_NAMESPACE_LFTS 2415551efdSEric Fiselier 2515551efdSEric Fiseliertemplate < 2615551efdSEric Fiselier class _Tp, class _Alloc 2715551efdSEric Fiselier , bool = uses_allocator<_Tp, _Alloc>::value 2815551efdSEric Fiselier , bool = __has_allocator_type<_Tp>::value 2915551efdSEric Fiselier > 3015551efdSEric Fiselierstruct __lfts_uses_allocator : public false_type {}; 3115551efdSEric Fiselier 3215551efdSEric Fiseliertemplate <class _Tp, class _Alloc> 3315551efdSEric Fiselierstruct __lfts_uses_allocator<_Tp, _Alloc, false, false> : public false_type {}; 3415551efdSEric Fiselier 3515551efdSEric Fiseliertemplate <class _Tp, class _Alloc, bool HasAlloc> 3615551efdSEric Fiselierstruct __lfts_uses_allocator<_Tp, _Alloc, true, HasAlloc> : public true_type {}; 3715551efdSEric Fiselier 3815551efdSEric Fiseliertemplate <class _Tp, class _Alloc> 3915551efdSEric Fiselierstruct __lfts_uses_allocator<_Tp, _Alloc, false, true> 4015551efdSEric Fiselier : public integral_constant<bool 4115551efdSEric Fiselier , is_convertible<_Alloc, typename _Tp::allocator_type>::value 4215551efdSEric Fiselier || is_same<erased_type, typename _Tp::allocator_type>::value 4315551efdSEric Fiselier > 4415551efdSEric Fiselier{}; 4515551efdSEric Fiselier 4615551efdSEric Fiseliertemplate <bool _UsesAlloc, class _Tp, class _Alloc, class ..._Args> 4715551efdSEric Fiselierstruct __lfts_uses_alloc_ctor_imp 4815551efdSEric Fiselier{ 4915551efdSEric Fiselier static const int value = 0; 5015551efdSEric Fiselier}; 5115551efdSEric Fiselier 5215551efdSEric Fiseliertemplate <class _Tp, class _Alloc, class ..._Args> 5315551efdSEric Fiselierstruct __lfts_uses_alloc_ctor_imp<true, _Tp, _Alloc, _Args...> 5415551efdSEric Fiselier{ 5515551efdSEric Fiselier static const bool __ic_first 5615551efdSEric Fiselier = is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value; 5715551efdSEric Fiselier 5815551efdSEric Fiselier static const bool __ic_second = 5915551efdSEric Fiselier conditional< 6015551efdSEric Fiselier __ic_first, 6115551efdSEric Fiselier false_type, 6215551efdSEric Fiselier is_constructible<_Tp, _Args..., _Alloc> 6315551efdSEric Fiselier >::type::value; 6415551efdSEric Fiselier 6515551efdSEric Fiselier static_assert(__ic_first || __ic_second, 6615551efdSEric Fiselier "Request for uses allocator construction is ill-formed"); 6715551efdSEric Fiselier 6815551efdSEric Fiselier static const int value = __ic_first ? 1 : 2; 6915551efdSEric Fiselier}; 7015551efdSEric Fiselier 7115551efdSEric Fiseliertemplate <class _Tp, class _Alloc, class ..._Args> 7215551efdSEric Fiselierstruct __lfts_uses_alloc_ctor 7315551efdSEric Fiselier : integral_constant<int, 7415551efdSEric Fiselier __lfts_uses_alloc_ctor_imp< 7515551efdSEric Fiselier __lfts_uses_allocator<_Tp, _Alloc>::value 7615551efdSEric Fiselier , _Tp, _Alloc, _Args... 7715551efdSEric Fiselier >::value 7815551efdSEric Fiselier > 7915551efdSEric Fiselier{}; 8015551efdSEric Fiselier 81050b064fSChristopher Di Bellatemplate <class _Tp, class _Allocator, class... _Args> 82050b064fSChristopher Di Bellainline _LIBCPP_INLINE_VISIBILITY 83050b064fSChristopher Di Bellavoid __user_alloc_construct_impl (integral_constant<int, 0>, _Tp *__storage, const _Allocator &, _Args &&... __args ) 84050b064fSChristopher Di Bella{ 85050b064fSChristopher Di Bella new (__storage) _Tp (_VSTD::forward<_Args>(__args)...); 86050b064fSChristopher Di Bella} 87050b064fSChristopher Di Bella 88050b064fSChristopher Di Bella// FIXME: This should have a version which takes a non-const alloc. 89050b064fSChristopher Di Bellatemplate <class _Tp, class _Allocator, class... _Args> 90050b064fSChristopher Di Bellainline _LIBCPP_INLINE_VISIBILITY 91050b064fSChristopher Di Bellavoid __user_alloc_construct_impl (integral_constant<int, 1>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) 92050b064fSChristopher Di Bella{ 93050b064fSChristopher Di Bella new (__storage) _Tp (allocator_arg, __a, _VSTD::forward<_Args>(__args)...); 94050b064fSChristopher Di Bella} 95050b064fSChristopher Di Bella 96050b064fSChristopher Di Bella// FIXME: This should have a version which takes a non-const alloc. 97050b064fSChristopher Di Bellatemplate <class _Tp, class _Allocator, class... _Args> 98050b064fSChristopher Di Bellainline _LIBCPP_INLINE_VISIBILITY 99050b064fSChristopher Di Bellavoid __user_alloc_construct_impl (integral_constant<int, 2>, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) 100050b064fSChristopher Di Bella{ 101050b064fSChristopher Di Bella new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a); 102050b064fSChristopher Di Bella} 103050b064fSChristopher Di Bella 10415551efdSEric Fiseliertemplate <class _Tp, class _Alloc, class ..._Args> 10515551efdSEric Fiselierinline _LIBCPP_INLINE_VISIBILITY 10615551efdSEric Fiseliervoid __lfts_user_alloc_construct( 10715551efdSEric Fiselier _Tp * __store, const _Alloc & __a, _Args &&... __args) 10815551efdSEric Fiselier{ 109050b064fSChristopher Di Bella ::std::experimental::fundamentals_v1::__user_alloc_construct_impl( 11015551efdSEric Fiselier typename __lfts_uses_alloc_ctor<_Tp, _Alloc, _Args...>::type() 11115551efdSEric Fiselier , __store, __a, _VSTD::forward<_Args>(__args)... 11215551efdSEric Fiselier ); 11315551efdSEric Fiselier} 11415551efdSEric Fiselier 11515551efdSEric Fiselier_LIBCPP_END_NAMESPACE_LFTS 11615551efdSEric Fiselier 11715551efdSEric Fiselier#endif /* _LIBCPP_EXPERIMENTAL___MEMORY */ 118