Skip to content

Commit

Permalink
Untag dispatch _Uses_allocator_construct (#2471)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
Co-authored-by: Casey Carter <cartec69@gmail.com>
  • Loading branch information
3 people authored Mar 19, 2022
1 parent cfc02a1 commit b380155
Showing 1 changed file with 29 additions and 58 deletions.
87 changes: 29 additions & 58 deletions stl/inc/xpolymorphic_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,78 +23,49 @@ _STL_DISABLE_CLANG_WARNINGS
_STD_BEGIN

#if !_HAS_CXX20
template <class _Ty, class _Outer_alloc, class _Inner_alloc, class... _Types>
void _Uses_allocator_construct2(
true_type, _Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner, _Types&&... _Args) {
// uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, allocator_arg_t case
allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, allocator_arg, _Inner, _STD forward<_Types>(_Args)...);
}

template <class _Ty, class _Outer_alloc, class _Inner_alloc, class... _Types>
void _Uses_allocator_construct2(
false_type, _Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner, _Types&&... _Args) {
// uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, non-allocator_arg_t case
static_assert(is_constructible_v<_Ty, _Types..., _Inner_alloc&>,
"N4700 23.10.7.2 [allocator.uses.construction]/1 requires "
"is_constructible_v<T, Args..., Alloc&> when uses_allocator_v<T, Alloc> is true and "
"is_constructible_v<T, allocator_arg_t, Alloc&, Args...> is false");
allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, _STD forward<_Types>(_Args)..., _Inner);
}

template <class _Ty, class _Outer_alloc, class _Inner_alloc, class... _Types>
void _Uses_allocator_construct1(
true_type, _Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner, _Types&&... _Args) {
// uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner,
// uses_allocator_v<_Ty, _Inner_alloc> case
using _IsConstructible = typename is_constructible<_Ty, allocator_arg_t, _Inner_alloc&, _Types...>::type;
_Uses_allocator_construct2(_IsConstructible{}, _Ptr, _Outer, _Inner, _STD forward<_Types>(_Args)...);
}

template <class _Ty, class _Outer_alloc, class _Inner_alloc, class... _Types>
void _Uses_allocator_construct1(false_type, _Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc&, _Types&&... _Args) {
// uses-allocator construction of *_Ptr by alloc _Outer, !uses_allocator_v<_Ty, _Inner_alloc> case
static_assert(is_constructible_v<_Ty, _Types...>,
"N4700 23.10.7.2 [allocator.uses.construction]/1 requires "
"is_constructible_v<T, Args...> when uses_allocator_v<T, Alloc> is false");
allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, _STD forward<_Types>(_Args)...);
}

template <class _Ty, class _Outer_alloc, class _Inner_alloc, class... _Types,
enable_if_t<!_Is_specialization_v<_Ty, pair>, int> = 0>
void _Uses_allocator_construct(_Ty* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner, _Types&&... _Args) {
// uses-allocator construction of *_Ptr by alloc _Outer propagating alloc _Inner, non-pair case
_Uses_allocator_construct1(uses_allocator<_Ty, _Inner_alloc>{}, _Ptr, _Outer, _Inner,
_STD forward<_Types>(_Args)...); // TRANSITION, if constexpr
}

template <class _Alloc, class... _Types>
auto _Uses_allocator_piecewise2(true_type, _Alloc& _Al, tuple<_Types...>&& _Tuple) {
return _STD tuple_cat(tuple<allocator_arg_t, _Alloc&>(allocator_arg, _Al), _STD move(_Tuple));
}

template <class _Alloc, class... _Types>
auto _Uses_allocator_piecewise2(false_type, _Alloc& _Al, tuple<_Types...>&& _Tuple) {
return _STD tuple_cat(_STD move(_Tuple), tuple<_Alloc&>(_Al));
if constexpr (uses_allocator_v<_Ty, _Inner_alloc>) {
if constexpr (is_constructible_v<_Ty, allocator_arg_t, _Inner_alloc&, _Types...>) {
allocator_traits<_Outer_alloc>::construct(
_Outer, _Ptr, allocator_arg, _Inner, _STD forward<_Types>(_Args)...);
} else {
static_assert(is_constructible_v<_Ty, _Types..., _Inner_alloc&>,
"N4901 [allocator.uses.trait]/1 requires "
"is_constructible_v<T, Args..., Alloc&> when uses_allocator_v<T, Alloc> is true and "
"is_constructible_v<T, allocator_arg_t, Alloc&, Args...> is false");
allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, _STD forward<_Types>(_Args)..., _Inner);
}
} else {
static_assert(is_constructible_v<_Ty, _Types...>,
"N4901 [allocator.uses.trait]/1 requires "
"is_constructible_v<T, Args...> when uses_allocator_v<T, Alloc> is false");
allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, _STD forward<_Types>(_Args)...);
}
}

template <class _Ty, class _Alloc, class... _Types>
auto _Uses_allocator_piecewise(true_type, _Alloc& _Al, tuple<_Types...>&& _Tuple) {
return _Uses_allocator_piecewise2(
is_constructible<_Ty, allocator_arg_t, _Alloc&, _Types...>(), _Al, _STD move(_Tuple));
}

template <class, class _Alloc, class... _Types>
tuple<_Types...>&& _Uses_allocator_piecewise(false_type, _Alloc&, tuple<_Types...>&& _Tuple) {
return _STD move(_Tuple);
decltype(auto) _Uses_allocator_piecewise(_Alloc& _Al, tuple<_Types...>&& _Tuple) {
if constexpr (uses_allocator_v<_Ty, _Alloc>) {
if constexpr (is_constructible_v<_Ty, allocator_arg_t, _Alloc&, _Types...>) {
return _STD tuple_cat(tuple<allocator_arg_t, _Alloc&>(allocator_arg, _Al), _STD move(_Tuple));
} else {
return _STD tuple_cat(_STD move(_Tuple), tuple<_Alloc&>(_Al));
}
} else {
return _STD move(_Tuple);
}
}

template <class _Ty1, class _Ty2, class _Outer_alloc, class _Inner_alloc, class... _Types1, class... _Types2>
void _Uses_allocator_construct_pair(pair<_Ty1, _Ty2>* const _Ptr, _Outer_alloc& _Outer, _Inner_alloc& _Inner,
tuple<_Types1...>&& _Val1, tuple<_Types2...>&& _Val2) {
// uses-allocator construction of pair from _Val1 and _Val2 by alloc _Outer propagating alloc _Inner
allocator_traits<_Outer_alloc>::construct(_Outer, _Ptr, piecewise_construct,
_Uses_allocator_piecewise<_Ty1>(uses_allocator<_Ty1, _Inner_alloc>{}, _Inner, _STD move(_Val1)),
_Uses_allocator_piecewise<_Ty2>(uses_allocator<_Ty2, _Inner_alloc>{}, _Inner, _STD move(_Val2)));
_Uses_allocator_piecewise<_Ty1>(_Inner, _STD move(_Val1)),
_Uses_allocator_piecewise<_Ty2>(_Inner, _STD move(_Val2)));
}

template <class _Ty1, class _Ty2, class _Outer_alloc, class _Inner_alloc, class... _Types1, class... _Types2>
Expand Down

0 comments on commit b380155

Please sign in to comment.