235 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H10#define _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H11 12#include <__config>13#include <__memory/construct_at.h>14#include <__memory/uses_allocator.h>15#include <__tuple/tuple_like_no_subrange.h>16#include <__type_traits/enable_if.h>17#include <__type_traits/remove_cv.h>18#include <__utility/declval.h>19#include <__utility/pair.h>20#include <__utility/piecewise_construct.h>21#include <tuple>22 23#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)24# pragma GCC system_header25#endif26 27_LIBCPP_PUSH_MACROS28#include <__undef_macros>29 30_LIBCPP_BEGIN_NAMESPACE_STD31 32#if _LIBCPP_STD_VER >= 1733 34template <class _Tp>35inline constexpr bool __is_cv_std_pair = __is_pair_v<remove_cv_t<_Tp>>;36 37template <class _Tp, class = void>38struct __uses_allocator_construction_args;39 40namespace __uses_allocator_detail {41 42template <class _Ap, class _Bp>43void __fun(const pair<_Ap, _Bp>&);44 45template <class _Tp>46decltype(__uses_allocator_detail::__fun(std::declval<_Tp>()), true_type()) __convertible_to_const_pair_ref_impl(int);47 48template <class>49false_type __convertible_to_const_pair_ref_impl(...);50 51template <class _Tp>52inline constexpr bool __convertible_to_const_pair_ref =53 decltype(__uses_allocator_detail::__convertible_to_const_pair_ref_impl<_Tp>(0))::value;54 55# if _LIBCPP_STD_VER >= 2356template <class _Tp, class _Up>57inline constexpr bool __uses_allocator_constraints =58 __is_cv_std_pair<_Tp> && !__pair_like_no_subrange<_Up> && !__convertible_to_const_pair_ref<_Up>;59# else60template <class _Tp, class _Up>61inline constexpr bool __uses_allocator_constraints = __is_cv_std_pair<_Tp> && !__convertible_to_const_pair_ref<_Up>;62# endif63 64} // namespace __uses_allocator_detail65 66template <class _Type, class _Alloc, class... _Args>67_LIBCPP_HIDE_FROM_ABI constexpr _Type __make_obj_using_allocator(const _Alloc& __alloc, _Args&&... __args);68 69template <class _Pair>70struct __uses_allocator_construction_args<_Pair, __enable_if_t<__is_cv_std_pair<_Pair>>> {71 template <class _Alloc, class _Tuple1, class _Tuple2>72 static _LIBCPP_HIDE_FROM_ABI constexpr auto73 __apply(const _Alloc& __alloc, piecewise_construct_t, _Tuple1&& __x, _Tuple2&& __y) noexcept {74 return std::make_tuple(75 piecewise_construct,76 std::apply(77 [&__alloc](auto&&... __args1) {78 return __uses_allocator_construction_args<typename _Pair::first_type>::__apply(79 __alloc, std::forward<decltype(__args1)>(__args1)...);80 },81 std::forward<_Tuple1>(__x)),82 std::apply(83 [&__alloc](auto&&... __args2) {84 return __uses_allocator_construction_args<typename _Pair::second_type>::__apply(85 __alloc, std::forward<decltype(__args2)>(__args2)...);86 },87 std::forward<_Tuple2>(__y)));88 }89 90 template <class _Alloc>91 static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc) noexcept {92 return __uses_allocator_construction_args<_Pair>::__apply(__alloc, piecewise_construct, tuple<>{}, tuple<>{});93 }94 95 template <class _Alloc, class _Up, class _Vp>96 static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _Up&& __u, _Vp&& __v) noexcept {97 return __uses_allocator_construction_args<_Pair>::__apply(98 __alloc,99 piecewise_construct,100 std::forward_as_tuple(std::forward<_Up>(__u)),101 std::forward_as_tuple(std::forward<_Vp>(__v)));102 }103 104# if _LIBCPP_STD_VER >= 23105 template <class _Alloc, class _Up, class _Vp>106 static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, pair<_Up, _Vp>& __pair) noexcept {107 return __uses_allocator_construction_args<_Pair>::__apply(108 __alloc, piecewise_construct, std::forward_as_tuple(__pair.first), std::forward_as_tuple(__pair.second));109 }110# endif111 112 template <class _Alloc, class _Up, class _Vp>113 static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, const pair<_Up, _Vp>& __pair) noexcept {114 return __uses_allocator_construction_args<_Pair>::__apply(115 __alloc, piecewise_construct, std::forward_as_tuple(__pair.first), std::forward_as_tuple(__pair.second));116 }117 118 template <class _Alloc, class _Up, class _Vp>119 static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, pair<_Up, _Vp>&& __pair) noexcept {120 return __uses_allocator_construction_args<_Pair>::__apply(121 __alloc,122 piecewise_construct,123 std::forward_as_tuple(std::get<0>(std::move(__pair))),124 std::forward_as_tuple(std::get<1>(std::move(__pair))));125 }126 127# if _LIBCPP_STD_VER >= 23128 template <class _Alloc, class _Up, class _Vp>129 static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, const pair<_Up, _Vp>&& __pair) noexcept {130 return __uses_allocator_construction_args<_Pair>::__apply(131 __alloc,132 piecewise_construct,133 std::forward_as_tuple(std::get<0>(std::move(__pair))),134 std::forward_as_tuple(std::get<1>(std::move(__pair))));135 }136 137 template < class _Alloc, __pair_like_no_subrange _PairLike>138 static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _PairLike&& __p) noexcept {139 return __uses_allocator_construction_args<_Pair>::__apply(140 __alloc,141 piecewise_construct,142 std::forward_as_tuple(std::get<0>(std::forward<_PairLike>(__p))),143 std::forward_as_tuple(std::get<1>(std::forward<_PairLike>(__p))));144 }145# endif146 147 template <class _Alloc,148 class _Type,149 __enable_if_t<__uses_allocator_detail::__uses_allocator_constraints<_Pair, _Type>, int> = 0>150 static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _Type&& __value) noexcept {151 struct __pair_constructor {152 using _PairMutable = remove_cv_t<_Pair>;153 154 _LIBCPP_HIDDEN constexpr auto __do_construct(const _PairMutable& __pair) const {155 return std::__make_obj_using_allocator<_PairMutable>(__alloc_, __pair);156 }157 158 _LIBCPP_HIDDEN constexpr auto __do_construct(_PairMutable&& __pair) const {159 return std::__make_obj_using_allocator<_PairMutable>(__alloc_, std::move(__pair));160 }161 162 const _Alloc& __alloc_;163 _Type& __value_;164 165 _LIBCPP_HIDDEN constexpr operator _PairMutable() const { return __do_construct(std::forward<_Type>(__value_)); }166 };167 168 return std::make_tuple(__pair_constructor{__alloc, __value});169 }170};171 172template <class _Type>173struct __uses_allocator_construction_args<_Type, __enable_if_t<!__is_cv_std_pair<_Type>>> {174 template <class _Alloc, class... _Args>175 static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _Args&&... __args) noexcept {176 if constexpr (!uses_allocator_v<remove_cv_t<_Type>, _Alloc> && is_constructible_v<_Type, _Args...>) {177 return std::forward_as_tuple(std::forward<_Args>(__args)...);178 } else if constexpr (uses_allocator_v<remove_cv_t<_Type>, _Alloc> &&179 is_constructible_v<_Type, allocator_arg_t, const _Alloc&, _Args...>) {180 return tuple<allocator_arg_t, const _Alloc&, _Args&&...>(allocator_arg, __alloc, std::forward<_Args>(__args)...);181 } else if constexpr (uses_allocator_v<remove_cv_t<_Type>, _Alloc> &&182 is_constructible_v<_Type, _Args..., const _Alloc&>) {183 return std::forward_as_tuple(std::forward<_Args>(__args)..., __alloc);184 } else {185 static_assert(186 sizeof(_Type) + 1 == 0, "If uses_allocator_v<Type> is true, the type has to be allocator-constructible");187 }188 }189};190 191template <class _Type, class _Alloc, class... _Args>192_LIBCPP_HIDE_FROM_ABI constexpr _Type __make_obj_using_allocator(const _Alloc& __alloc, _Args&&... __args) {193 return std::make_from_tuple<_Type>(194 __uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...));195}196 197template <class _Type, class _Alloc, class... _Args>198_LIBCPP_HIDE_FROM_ABI constexpr _Type*199__uninitialized_construct_using_allocator(_Type* __ptr, const _Alloc& __alloc, _Args&&... __args) {200 return std::apply(201 [&__ptr](auto&&... __xs) { return std::__construct_at(__ptr, std::forward<decltype(__xs)>(__xs)...); },202 __uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...));203}204 205#endif // _LIBCPP_STD_VER >= 17206 207#if _LIBCPP_STD_VER >= 20208 209template <class _Type, class _Alloc, class... _Args>210_LIBCPP_HIDE_FROM_ABI constexpr auto uses_allocator_construction_args(const _Alloc& __alloc, _Args&&... __args) noexcept211 -> decltype(__uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...)) {212 return /*--*/ __uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...);213}214 215template <class _Type, class _Alloc, class... _Args>216_LIBCPP_HIDE_FROM_ABI constexpr auto make_obj_using_allocator(const _Alloc& __alloc, _Args&&... __args)217 -> decltype(std::__make_obj_using_allocator<_Type>(__alloc, std::forward<_Args>(__args)...)) {218 return /*--*/ std::__make_obj_using_allocator<_Type>(__alloc, std::forward<_Args>(__args)...);219}220 221template <class _Type, class _Alloc, class... _Args>222_LIBCPP_HIDE_FROM_ABI constexpr auto223uninitialized_construct_using_allocator(_Type* __ptr, const _Alloc& __alloc, _Args&&... __args)224 -> decltype(std::__uninitialized_construct_using_allocator(__ptr, __alloc, std::forward<_Args>(__args)...)) {225 return /*--*/ std::__uninitialized_construct_using_allocator(__ptr, __alloc, std::forward<_Args>(__args)...);226}227 228#endif // _LIBCPP_STD_VER >= 20229 230_LIBCPP_END_NAMESPACE_STD231 232_LIBCPP_POP_MACROS233 234#endif // _LIBCPP___MEMORY_USES_ALLOCATOR_CONSTRUCTION_H235