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