[libcxx-commits] [libcxx] beecf2c - [libc++] Fix missing declarations of uses_allocator_construction_args (#67044)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 1 05:54:46 PDT 2024
Author: Shivam
Date: 2024-08-01T08:54:43-04:00
New Revision: beecf2c6052485d99c6db86422aebdb433f98b5a
URL: https://github.com/llvm/llvm-project/commit/beecf2c6052485d99c6db86422aebdb433f98b5a
DIFF: https://github.com/llvm/llvm-project/commit/beecf2c6052485d99c6db86422aebdb433f98b5a.diff
LOG: [libc++] Fix missing declarations of uses_allocator_construction_args (#67044)
We were not declaring `__uses_allocator_construction_args` helper
functions, leading to several valid uses failing to compile. This
patch solves the problem by moving these helper functions into a
struct, which also reduces the amount of redundant SFINAE we need
to perform since most overloads are checking for a cv-qualfied pair.
Fixes #66714
Co-authored-by: Louis Dionne <ldionne.2 at gmail.com>
Added:
Modified:
libcxx/include/__memory/uses_allocator_construction.h
libcxx/test/std/utilities/memory/allocator.uses/allocator.uses.construction/uses_allocator_construction_args.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__memory/uses_allocator_construction.h b/libcxx/include/__memory/uses_allocator_construction.h
index 5e5819d4c281e..955879ffc5845 100644
--- a/libcxx/include/__memory/uses_allocator_construction.h
+++ b/libcxx/include/__memory/uses_allocator_construction.h
@@ -40,104 +40,8 @@ inline constexpr bool __is_std_pair<pair<_Type1, _Type2>> = true;
template <class _Tp>
inline constexpr bool __is_cv_std_pair = __is_std_pair<remove_cv_t<_Tp>>;
-template <class _Type, class _Alloc, class... _Args, __enable_if_t<!__is_cv_std_pair<_Type>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto
-__uses_allocator_construction_args(const _Alloc& __alloc, _Args&&... __args) noexcept {
- if constexpr (!uses_allocator_v<remove_cv_t<_Type>, _Alloc> && is_constructible_v<_Type, _Args...>) {
- return std::forward_as_tuple(std::forward<_Args>(__args)...);
- } else if constexpr (uses_allocator_v<remove_cv_t<_Type>, _Alloc> &&
- is_constructible_v<_Type, allocator_arg_t, const _Alloc&, _Args...>) {
- return tuple<allocator_arg_t, const _Alloc&, _Args&&...>(allocator_arg, __alloc, std::forward<_Args>(__args)...);
- } else if constexpr (uses_allocator_v<remove_cv_t<_Type>, _Alloc> &&
- is_constructible_v<_Type, _Args..., const _Alloc&>) {
- return std::forward_as_tuple(std::forward<_Args>(__args)..., __alloc);
- } else {
- static_assert(
- sizeof(_Type) + 1 == 0, "If uses_allocator_v<Type> is true, the type has to be allocator-constructible");
- }
-}
-
-template <class _Pair, class _Alloc, class _Tuple1, class _Tuple2, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto __uses_allocator_construction_args(
- const _Alloc& __alloc, piecewise_construct_t, _Tuple1&& __x, _Tuple2&& __y) noexcept {
- return std::make_tuple(
- piecewise_construct,
- std::apply(
- [&__alloc](auto&&... __args1) {
- return std::__uses_allocator_construction_args<typename _Pair::first_type>(
- __alloc, std::forward<decltype(__args1)>(__args1)...);
- },
- std::forward<_Tuple1>(__x)),
- std::apply(
- [&__alloc](auto&&... __args2) {
- return std::__uses_allocator_construction_args<typename _Pair::second_type>(
- __alloc, std::forward<decltype(__args2)>(__args2)...);
- },
- std::forward<_Tuple2>(__y)));
-}
-
-template <class _Pair, class _Alloc, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto __uses_allocator_construction_args(const _Alloc& __alloc) noexcept {
- return std::__uses_allocator_construction_args<_Pair>(__alloc, piecewise_construct, tuple<>{}, tuple<>{});
-}
-
-template <class _Pair, class _Alloc, class _Up, class _Vp, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto
-__uses_allocator_construction_args(const _Alloc& __alloc, _Up&& __u, _Vp&& __v) noexcept {
- return std::__uses_allocator_construction_args<_Pair>(
- __alloc,
- piecewise_construct,
- std::forward_as_tuple(std::forward<_Up>(__u)),
- std::forward_as_tuple(std::forward<_Vp>(__v)));
-}
-
-# if _LIBCPP_STD_VER >= 23
-template <class _Pair, class _Alloc, class _Up, class _Vp, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto
-__uses_allocator_construction_args(const _Alloc& __alloc, pair<_Up, _Vp>& __pair) noexcept {
- return std::__uses_allocator_construction_args<_Pair>(
- __alloc, piecewise_construct, std::forward_as_tuple(__pair.first), std::forward_as_tuple(__pair.second));
-}
-# endif
-
-template <class _Pair, class _Alloc, class _Up, class _Vp, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto
-__uses_allocator_construction_args(const _Alloc& __alloc, const pair<_Up, _Vp>& __pair) noexcept {
- return std::__uses_allocator_construction_args<_Pair>(
- __alloc, piecewise_construct, std::forward_as_tuple(__pair.first), std::forward_as_tuple(__pair.second));
-}
-
-template <class _Pair, class _Alloc, class _Up, class _Vp, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto
-__uses_allocator_construction_args(const _Alloc& __alloc, pair<_Up, _Vp>&& __pair) noexcept {
- return std::__uses_allocator_construction_args<_Pair>(
- __alloc,
- piecewise_construct,
- std::forward_as_tuple(std::get<0>(std::move(__pair))),
- std::forward_as_tuple(std::get<1>(std::move(__pair))));
-}
-
-# if _LIBCPP_STD_VER >= 23
-template <class _Pair, class _Alloc, class _Up, class _Vp, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto
-__uses_allocator_construction_args(const _Alloc& __alloc, const pair<_Up, _Vp>&& __pair) noexcept {
- return std::__uses_allocator_construction_args<_Pair>(
- __alloc,
- piecewise_construct,
- std::forward_as_tuple(std::get<0>(std::move(__pair))),
- std::forward_as_tuple(std::get<1>(std::move(__pair))));
-}
-
-template <class _Pair, class _Alloc, __pair_like_no_subrange _PairLike, __enable_if_t<__is_cv_std_pair<_Pair>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto
-__uses_allocator_construction_args(const _Alloc& __alloc, _PairLike&& __p) noexcept {
- return std::__uses_allocator_construction_args<_Pair>(
- __alloc,
- piecewise_construct,
- std::forward_as_tuple(std::get<0>(std::forward<_PairLike>(__p))),
- std::forward_as_tuple(std::get<1>(std::forward<_PairLike>(__p))));
-}
-# endif
+template <class _Tp, class = void>
+struct __uses_allocator_construction_args;
namespace __uses_allocator_detail {
@@ -165,46 +69,135 @@ inline constexpr bool __uses_allocator_constraints = __is_cv_std_pair<_Tp> && !_
} // namespace __uses_allocator_detail
-template < class _Pair,
- class _Alloc,
- class _Type,
- __enable_if_t<__uses_allocator_detail::__uses_allocator_constraints<_Pair, _Type>, int> = 0>
-_LIBCPP_HIDE_FROM_ABI constexpr auto
-__uses_allocator_construction_args(const _Alloc& __alloc, _Type&& __value) noexcept;
-
template <class _Type, class _Alloc, class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr _Type __make_obj_using_allocator(const _Alloc& __alloc, _Args&&... __args);
-template < class _Pair,
- class _Alloc,
- class _Type,
- __enable_if_t< __uses_allocator_detail::__uses_allocator_constraints<_Pair, _Type>, int>>
-_LIBCPP_HIDE_FROM_ABI constexpr auto
-__uses_allocator_construction_args(const _Alloc& __alloc, _Type&& __value) noexcept {
- struct __pair_constructor {
- using _PairMutable = remove_cv_t<_Pair>;
+template <class _Pair>
+struct __uses_allocator_construction_args<_Pair, __enable_if_t<__is_cv_std_pair<_Pair>>> {
+ template <class _Alloc, class _Tuple1, class _Tuple2>
+ static _LIBCPP_HIDE_FROM_ABI constexpr auto
+ __apply(const _Alloc& __alloc, piecewise_construct_t, _Tuple1&& __x, _Tuple2&& __y) noexcept {
+ return std::make_tuple(
+ piecewise_construct,
+ std::apply(
+ [&__alloc](auto&&... __args1) {
+ return __uses_allocator_construction_args<typename _Pair::first_type>::__apply(
+ __alloc, std::forward<decltype(__args1)>(__args1)...);
+ },
+ std::forward<_Tuple1>(__x)),
+ std::apply(
+ [&__alloc](auto&&... __args2) {
+ return __uses_allocator_construction_args<typename _Pair::second_type>::__apply(
+ __alloc, std::forward<decltype(__args2)>(__args2)...);
+ },
+ std::forward<_Tuple2>(__y)));
+ }
- _LIBCPP_HIDDEN constexpr auto __do_construct(const _PairMutable& __pair) const {
- return std::__make_obj_using_allocator<_PairMutable>(__alloc_, __pair);
- }
+ template <class _Alloc>
+ static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc) noexcept {
+ return __uses_allocator_construction_args<_Pair>::__apply(__alloc, piecewise_construct, tuple<>{}, tuple<>{});
+ }
- _LIBCPP_HIDDEN constexpr auto __do_construct(_PairMutable&& __pair) const {
- return std::__make_obj_using_allocator<_PairMutable>(__alloc_, std::move(__pair));
- }
+ template <class _Alloc, class _Up, class _Vp>
+ static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _Up&& __u, _Vp&& __v) noexcept {
+ return __uses_allocator_construction_args<_Pair>::__apply(
+ __alloc,
+ piecewise_construct,
+ std::forward_as_tuple(std::forward<_Up>(__u)),
+ std::forward_as_tuple(std::forward<_Vp>(__v)));
+ }
- const _Alloc& __alloc_;
- _Type& __value_;
+# if _LIBCPP_STD_VER >= 23
+ template <class _Alloc, class _Up, class _Vp>
+ static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, pair<_Up, _Vp>& __pair) noexcept {
+ return __uses_allocator_construction_args<_Pair>::__apply(
+ __alloc, piecewise_construct, std::forward_as_tuple(__pair.first), std::forward_as_tuple(__pair.second));
+ }
+# endif
- _LIBCPP_HIDDEN constexpr operator _PairMutable() const { return __do_construct(std::forward<_Type>(__value_)); }
- };
+ template <class _Alloc, class _Up, class _Vp>
+ static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, const pair<_Up, _Vp>& __pair) noexcept {
+ return __uses_allocator_construction_args<_Pair>::__apply(
+ __alloc, piecewise_construct, std::forward_as_tuple(__pair.first), std::forward_as_tuple(__pair.second));
+ }
- return std::make_tuple(__pair_constructor{__alloc, __value});
-}
+ template <class _Alloc, class _Up, class _Vp>
+ static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, pair<_Up, _Vp>&& __pair) noexcept {
+ return __uses_allocator_construction_args<_Pair>::__apply(
+ __alloc,
+ piecewise_construct,
+ std::forward_as_tuple(std::get<0>(std::move(__pair))),
+ std::forward_as_tuple(std::get<1>(std::move(__pair))));
+ }
+
+# if _LIBCPP_STD_VER >= 23
+ template <class _Alloc, class _Up, class _Vp>
+ static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, const pair<_Up, _Vp>&& __pair) noexcept {
+ return __uses_allocator_construction_args<_Pair>::__apply(
+ __alloc,
+ piecewise_construct,
+ std::forward_as_tuple(std::get<0>(std::move(__pair))),
+ std::forward_as_tuple(std::get<1>(std::move(__pair))));
+ }
+
+ template < class _Alloc, __pair_like_no_subrange _PairLike>
+ static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _PairLike&& __p) noexcept {
+ return __uses_allocator_construction_args<_Pair>::__apply(
+ __alloc,
+ piecewise_construct,
+ std::forward_as_tuple(std::get<0>(std::forward<_PairLike>(__p))),
+ std::forward_as_tuple(std::get<1>(std::forward<_PairLike>(__p))));
+ }
+# endif
+
+ template <class _Alloc,
+ class _Type,
+ __enable_if_t<__uses_allocator_detail::__uses_allocator_constraints<_Pair, _Type>, int> = 0>
+ static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _Type&& __value) noexcept {
+ struct __pair_constructor {
+ using _PairMutable = remove_cv_t<_Pair>;
+
+ _LIBCPP_HIDDEN constexpr auto __do_construct(const _PairMutable& __pair) const {
+ return std::__make_obj_using_allocator<_PairMutable>(__alloc_, __pair);
+ }
+
+ _LIBCPP_HIDDEN constexpr auto __do_construct(_PairMutable&& __pair) const {
+ return std::__make_obj_using_allocator<_PairMutable>(__alloc_, std::move(__pair));
+ }
+
+ const _Alloc& __alloc_;
+ _Type& __value_;
+
+ _LIBCPP_HIDDEN constexpr operator _PairMutable() const { return __do_construct(std::forward<_Type>(__value_)); }
+ };
+
+ return std::make_tuple(__pair_constructor{__alloc, __value});
+ }
+};
+
+template <class _Type>
+struct __uses_allocator_construction_args<_Type, __enable_if_t<!__is_cv_std_pair<_Type>>> {
+ template <class _Alloc, class... _Args>
+ static _LIBCPP_HIDE_FROM_ABI constexpr auto __apply(const _Alloc& __alloc, _Args&&... __args) noexcept {
+ if constexpr (!uses_allocator_v<remove_cv_t<_Type>, _Alloc> && is_constructible_v<_Type, _Args...>) {
+ return std::forward_as_tuple(std::forward<_Args>(__args)...);
+ } else if constexpr (uses_allocator_v<remove_cv_t<_Type>, _Alloc> &&
+ is_constructible_v<_Type, allocator_arg_t, const _Alloc&, _Args...>) {
+ return tuple<allocator_arg_t, const _Alloc&, _Args&&...>(allocator_arg, __alloc, std::forward<_Args>(__args)...);
+ } else if constexpr (uses_allocator_v<remove_cv_t<_Type>, _Alloc> &&
+ is_constructible_v<_Type, _Args..., const _Alloc&>) {
+ return std::forward_as_tuple(std::forward<_Args>(__args)..., __alloc);
+ } else {
+ static_assert(
+ sizeof(_Type) + 1 == 0, "If uses_allocator_v<Type> is true, the type has to be allocator-constructible");
+ }
+ }
+};
template <class _Type, class _Alloc, class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr _Type __make_obj_using_allocator(const _Alloc& __alloc, _Args&&... __args) {
return std::make_from_tuple<_Type>(
- std::__uses_allocator_construction_args<_Type>(__alloc, std::forward<_Args>(__args)...));
+ __uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...));
}
template <class _Type, class _Alloc, class... _Args>
@@ -212,7 +205,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Type*
__uninitialized_construct_using_allocator(_Type* __ptr, const _Alloc& __alloc, _Args&&... __args) {
return std::apply(
[&__ptr](auto&&... __xs) { return std::__construct_at(__ptr, std::forward<decltype(__xs)>(__xs)...); },
- std::__uses_allocator_construction_args<_Type>(__alloc, std::forward<_Args>(__args)...));
+ __uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...));
}
#endif // _LIBCPP_STD_VER >= 17
@@ -221,8 +214,8 @@ __uninitialized_construct_using_allocator(_Type* __ptr, const _Alloc& __alloc, _
template <class _Type, class _Alloc, class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr auto uses_allocator_construction_args(const _Alloc& __alloc, _Args&&... __args) noexcept
- -> decltype(std::__uses_allocator_construction_args<_Type>(__alloc, std::forward<_Args>(__args)...)) {
- return /*--*/ std::__uses_allocator_construction_args<_Type>(__alloc, std::forward<_Args>(__args)...);
+ -> decltype(__uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...)) {
+ return /*--*/ __uses_allocator_construction_args<_Type>::__apply(__alloc, std::forward<_Args>(__args)...);
}
template <class _Type, class _Alloc, class... _Args>
diff --git a/libcxx/test/std/utilities/memory/allocator.uses/allocator.uses.construction/uses_allocator_construction_args.pass.cpp b/libcxx/test/std/utilities/memory/allocator.uses/allocator.uses.construction/uses_allocator_construction_args.pass.cpp
index ab3c039497dd9..235a93987fe48 100644
--- a/libcxx/test/std/utilities/memory/allocator.uses/allocator.uses.construction/uses_allocator_construction_args.pass.cpp
+++ b/libcxx/test/std/utilities/memory/allocator.uses/allocator.uses.construction/uses_allocator_construction_args.pass.cpp
@@ -121,6 +121,63 @@ constexpr void testOne() {
assert(std::get<2>(std::get<1>(ret)) == 3);
assert(std::get<0>(std::get<2>(ret)) == 4);
}
+ {
+ // Tests for ensuring forward declarations of uses_allocator_construction_args
+ // See https://github.com/llvm/llvm-project/issues/66714.
+ {
+ using NestedPairType = std::pair<int, std::pair<int, UsesAllocArgT>>;
+ std::same_as<std::tuple<
+ std::piecewise_construct_t,
+ std::tuple<>,
+ std::tuple<std::piecewise_construct_t, std::tuple<>, std::tuple<std::allocator_arg_t, const Alloc&>>>> auto
+ ret = test_uses_allocator_construction_args<NestedPairType>(a);
+ (void)ret;
+ }
+ {
+ using NestedPairType = std::pair<int, std::pair<UsesAllocArgT, int>>;
+ std::same_as<std::tuple<
+ std::piecewise_construct_t,
+ std::tuple<>,
+ std::tuple<std::piecewise_construct_t, std::tuple<std::allocator_arg_t, const Alloc&>, std::tuple<>>>> auto
+ ret = test_uses_allocator_construction_args<NestedPairType>(a);
+ (void)ret;
+ }
+ {
+ using PairType = std::pair<int, int>;
+ int up = 1;
+ int vp = 2;
+
+ std::same_as<std::tuple<std::piecewise_construct_t, std::tuple<int&&>, std::tuple<int&&>>> auto ret =
+ test_uses_allocator_construction_args<PairType>(a, std::move(up), std::move(vp));
+ (void)ret;
+ }
+ {
+ using PairType = const std::pair<int, int>;
+ PairType p(1, 2);
+
+ std::same_as<std::tuple<std::piecewise_construct_t, std::tuple<const int&>, std::tuple<const int&>>> auto ret =
+ test_uses_allocator_construction_args<PairType>(a, p);
+ (void)ret;
+ }
+ {
+ using PairType = std::pair<int, int>;
+ PairType p(1, 2);
+
+ std::same_as<std::tuple<std::piecewise_construct_t, std::tuple<int&&>, std::tuple<int&&>>> auto ret =
+ test_uses_allocator_construction_args<PairType>(a, std::move(p));
+ (void)ret;
+ }
+#if TEST_STD_VER >= 23
+ {
+ using PairType = const std::pair<int, int>;
+ PairType p(1, 2);
+
+ std::same_as<std::tuple<std::piecewise_construct_t, std::tuple<const int&&>, std::tuple<const int&&>>> auto ret =
+ test_uses_allocator_construction_args<PairType>(a, std::move(p));
+ (void)ret;
+ }
+#endif
+ }
#if TEST_STD_VER >= 23
{
std::pair p{3, 4};
More information about the libcxx-commits
mailing list