2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP_EXPERIMENTAL___MEMORY
11 #define _LIBCPP_EXPERIMENTAL___MEMORY
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
22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23 # pragma GCC system_header
26 _LIBCPP_BEGIN_NAMESPACE_LFTS
28 template < class _Tp, class _Alloc, bool = uses_allocator<_Tp, _Alloc>::value, bool = __has_allocator_type<_Tp>::value >
29 struct __lfts_uses_allocator : public false_type {};
31 template <class _Tp, class _Alloc>
32 struct __lfts_uses_allocator<_Tp, _Alloc, false, false> : public false_type {};
34 template <class _Tp, class _Alloc, bool HasAlloc>
35 struct __lfts_uses_allocator<_Tp, _Alloc, true, HasAlloc> : public true_type {};
37 template <class _Tp, class _Alloc>
38 struct __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 > {};
43 template <bool _UsesAlloc, class _Tp, class _Alloc, class... _Args>
44 struct __lfts_uses_alloc_ctor_imp {
45 static const int value = 0;
48 template <class _Tp, class _Alloc, class... _Args>
49 struct __lfts_uses_alloc_ctor_imp<true, _Tp, _Alloc, _Args...> {
50 static const bool __ic_first = is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value;
52 static const bool __ic_second =
53 __conditional_t< __ic_first, false_type, is_constructible<_Tp, _Args..., _Alloc> >::value;
55 static_assert(__ic_first || __ic_second, "Request for uses allocator construction is ill-formed");
57 static const int value = __ic_first ? 1 : 2;
60 template <class _Tp, class _Alloc, class... _Args>
61 struct __lfts_uses_alloc_ctor
64 __lfts_uses_alloc_ctor_imp< __lfts_uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args... >::value > {};
66 template <class _Tp, class _Allocator, class... _Args>
67 inline _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)...);
72 // FIXME: This should have a version which takes a non-const alloc.
73 template <class _Tp, class _Allocator, class... _Args>
74 inline _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)...);
79 // FIXME: This should have a version which takes a non-const alloc.
80 template <class _Tp, class _Allocator, class... _Args>
81 inline _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);
86 template <class _Tp, class _Alloc, class... _Args>
87 inline _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)...);
92 _LIBCPP_END_NAMESPACE_LFTS
94 #endif /* _LIBCPP_EXPERIMENTAL___MEMORY */