Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P2321R2 zip: Make tuple, pair, and vector<bool>::reference indirectly_writable #2687

Merged
merged 5 commits into from
May 5, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 226 additions & 34 deletions stl/inc/tuple

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions stl/inc/type_traits
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,14 @@ struct is_assignable : bool_constant<__is_assignable(_To, _From)> {}; // determi
template <class _To, class _From>
_INLINE_VAR constexpr bool is_assignable_v = __is_assignable(_To, _From);

#if defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__CUDACC__)
template <class _To, class _From>
struct _Is_assignable_no_precondition_check : bool_constant<__is_assignable_no_precondition_check(_To, _From)> {};
#else // ^^^ Use intrinsic / intrinsic not supported vvv
template <class _To, class _From>
using _Is_assignable_no_precondition_check = is_assignable<_To, _From>;
#endif // defined(_IS_ASSIGNABLE_NOCHECK_SUPPORTED) && !defined(__CUDACC__)

template <class _Ty>
struct is_copy_assignable
: bool_constant<__is_assignable(add_lvalue_reference_t<_Ty>, add_lvalue_reference_t<const _Ty>)> {
Expand Down
113 changes: 113 additions & 0 deletions stl/inc/utility
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,15 @@ struct pair { // store a pair of values
pair(const pair&) = default;
pair(pair&&) = default;

#if _HAS_CXX23
template <class _Other1, class _Other2,
enable_if_t<conjunction_v<is_constructible<_Ty1, _Other1&>, is_constructible<_Ty2, _Other2&>>, int> = 0>
constexpr explicit(!conjunction_v<is_convertible<_Other1&, _Ty1>, is_convertible<_Other2&, _Ty2>>)
pair(pair<_Other1, _Other2>& _Right) noexcept(
is_nothrow_constructible_v<_Ty1, _Other1&>&& is_nothrow_constructible_v<_Ty2, _Other2&>) // strengthened
: first(_Right.first), second(_Right.second) {}
#endif // _HAS_CXX23

#if _HAS_CONDITIONAL_EXPLICIT
template <class _Other1, class _Other2,
enable_if_t<conjunction_v<is_constructible<_Ty1, const _Other1&>, is_constructible<_Ty2, const _Other2&>>,
Expand Down Expand Up @@ -263,6 +272,16 @@ struct pair { // store a pair of values
: first(_STD forward<_Other1>(_Right.first)), second(_STD forward<_Other2>(_Right.second)) {}
#endif // ^^^ !_HAS_CONDITIONAL_EXPLICIT ^^^

#if _HAS_CXX23
template <class _Other1, class _Other2,
enable_if_t<conjunction_v<is_constructible<_Ty1, const _Other1>, is_constructible<_Ty2, const _Other2>>, int> =
0>
constexpr explicit(!conjunction_v<is_convertible<const _Other1, _Ty1>, is_convertible<const _Other2, _Ty2>>)
pair(const pair<_Other1, _Other2>&& _Right) noexcept(is_nothrow_constructible_v<_Ty1, const _Other1>&&
is_nothrow_constructible_v<_Ty2, const _Other2>) // strengthened
: first(_STD forward<const _Other1>(_Right.first)), second(_STD forward<const _Other2>(_Right.second)) {}
#endif // _HAS_CXX23

template <class _Tuple1, class _Tuple2, size_t... _Indexes1, size_t... _Indexes2>
constexpr pair(_Tuple1& _Val1, _Tuple2& _Val2, index_sequence<_Indexes1...>, index_sequence<_Indexes2...>)
: first(_Tuple_get<_Indexes1>(_STD move(_Val1))...), second(_Tuple_get<_Indexes2>(_STD move(_Val2))...) {}
Expand All @@ -284,6 +303,20 @@ struct pair { // store a pair of values
return *this;
}

#if _HAS_CXX23
template <class _Myself = pair,
enable_if_t<conjunction_v<_Is_copy_assignable_no_precondition_check<const typename _Myself::first_type>,
_Is_copy_assignable_no_precondition_check<const typename _Myself::second_type>>,
int> = 0>
constexpr const pair& operator=(_Identity_t<const _Myself&> _Right) const
noexcept(conjunction_v<is_nothrow_copy_assignable<const _Ty1>,
is_nothrow_copy_assignable<const _Ty2>>) /* strengthened */ {
first = _Right.first;
second = _Right.second;
return *this;
}
#endif // _HAS_CXX23

template <class _Myself = pair,
enable_if_t<conjunction_v<_Is_move_assignable_no_precondition_check<typename _Myself::first_type>,
_Is_move_assignable_no_precondition_check<typename _Myself::second_type>>,
Expand All @@ -295,6 +328,20 @@ struct pair { // store a pair of values
return *this;
}

#if _HAS_CXX23
template <class _Myself = pair,
enable_if_t<conjunction_v<_Is_assignable_no_precondition_check<const typename _Myself::first_type&, _Ty1>,
_Is_assignable_no_precondition_check<const typename _Myself::second_type&, _Ty2>>,
int> = 0>
constexpr const pair& operator=(_Identity_t<_Myself&&> _Right) const
noexcept(conjunction_v<is_nothrow_assignable<const _Ty1&, _Ty1>,
is_nothrow_assignable<const _Ty2&, _Ty2>>) /* strengthened */ {
first = _STD forward<_Ty1>(_Right.first);
second = _STD forward<_Ty2>(_Right.second);
return *this;
}
#endif // _HAS_CXX23

template <class _Other1, class _Other2,
enable_if_t<conjunction_v<negation<is_same<pair, pair<_Other1, _Other2>>>, is_assignable<_Ty1&, const _Other1&>,
is_assignable<_Ty2&, const _Other2&>>,
Expand All @@ -307,6 +354,20 @@ struct pair { // store a pair of values
return *this;
}

#if _HAS_CXX23
template <class _Other1, class _Other2,
enable_if_t<conjunction_v<negation<is_same<pair, pair<_Other1, _Other2>>>,
is_assignable<const _Ty1&, const _Other1&>, is_assignable<const _Ty2&, const _Other2&>>,
int> = 0>
constexpr const pair& operator=(const pair<_Other1, _Other2>& _Right) const
noexcept(is_nothrow_assignable_v<const _Ty1&, const _Other1&>&&
is_nothrow_assignable_v<const _Ty2&, const _Other2&>) /* strengthened */ {
first = _Right.first;
second = _Right.second;
return *this;
}
#endif // _HAS_CXX23

template <class _Other1, class _Other2,
enable_if_t<conjunction_v<negation<is_same<pair, pair<_Other1, _Other2>>>, is_assignable<_Ty1&, _Other1>,
is_assignable<_Ty2&, _Other2>>,
Expand All @@ -318,6 +379,20 @@ struct pair { // store a pair of values
return *this;
}

#if _HAS_CXX23
template <class _Other1, class _Other2,
enable_if_t<conjunction_v<negation<is_same<pair, pair<_Other1, _Other2>>>, is_assignable<const _Ty1&, _Other1>,
is_assignable<const _Ty2&, _Other2>>,
int> = 0>
constexpr const pair& operator=(pair<_Other1, _Other2>&& _Right) const
noexcept(is_nothrow_assignable_v<const _Ty1&, _Other1>&&
is_nothrow_assignable_v<const _Ty2&, _Other2>) /* strengthened */ {
first = _STD forward<_Other1>(_Right.first);
second = _STD forward<_Other2>(_Right.second);
return *this;
}
#endif // _HAS_CXX23

_CONSTEXPR20 void swap(pair& _Right) noexcept(
_Is_nothrow_swappable<_Ty1>::value&& _Is_nothrow_swappable<_Ty2>::value) {
if (this != _STD addressof(_Right)) {
Expand All @@ -326,6 +401,16 @@ struct pair { // store a pair of values
}
}

#if _HAS_CXX23
constexpr void swap(const pair& _Right) const
noexcept(_Is_nothrow_swappable<const _Ty1>::value&& _Is_nothrow_swappable<const _Ty2>::value) {
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
if (this != _STD addressof(_Right)) {
_Swap_adl(first, _Right.first);
_Swap_adl(second, _Right.second);
}
}
#endif // _HAS_CXX23

_Ty1 first; // the first stored value
_Ty2 second; // the second stored value
};
Expand All @@ -340,6 +425,15 @@ _CONSTEXPR20 void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right) noexce
_Left.swap(_Right);
}

#if _HAS_CXX23
template <class _Ty1, class _Ty2,
enable_if_t<_Is_swappable<const _Ty1>::value && _Is_swappable<const _Ty2>::value, int> = 0>
constexpr void swap(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) noexcept(
noexcept(_Left.swap(_Right))) {
_Left.swap(_Right);
}
#endif // _HAS_CXX23

template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool operator==(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) {
return _Left.first == _Right.first && _Left.second == _Right.second;
Expand Down Expand Up @@ -383,6 +477,25 @@ _NODISCARD constexpr bool operator>=(const pair<_Ty1, _Ty2>& _Left, const pair<_
}
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^

#if _HAS_CXX23
template <class _Ty1, class _Ty2, class _Uty1, class _Uty2, template <class> class _TQual,
template <class> class _UQual>
requires requires {
typename pair<common_reference_t<_TQual<_Ty1>, _UQual<_Uty1>>, common_reference_t<_TQual<_Ty2>, _UQual<_Uty2>>>;
}
struct basic_common_reference<pair<_Ty1, _Ty2>, pair<_Uty1, _Uty2>, _TQual, _UQual> {
using type = pair<common_reference_t<_TQual<_Ty1>, _UQual<_Uty1>>, common_reference_t<_TQual<_Ty2>, _UQual<_Uty2>>>;
};

template <class _Ty1, class _Ty2, class _Uty1, class _Uty2>
requires requires {
typename pair<common_type_t<_Ty1, _Uty1>, common_type_t<_Ty2, _Uty2>>;
}
struct common_type<pair<_Ty1, _Ty2>, pair<_Uty1, _Uty2>> {
using type = pair<common_type_t<_Ty1, _Uty1>, common_type_t<_Ty2, _Uty2>>;
};
#endif // _HAS_CXX23

template <class _Ty>
struct _Unrefwrap_helper { // leave unchanged if not a reference_wrapper
using type = _Ty;
Expand Down
12 changes: 12 additions & 0 deletions stl/inc/vector
Original file line number Diff line number Diff line change
Expand Up @@ -2274,6 +2274,18 @@ public:
return *this;
}

#if _HAS_CXX23
constexpr const _Vb_reference& operator=(bool _Val) const noexcept {
if (_Val) {
*const_cast<_Vbase*>(_Getptr()) |= _Mask();
} else {
*const_cast<_Vbase*>(_Getptr()) &= ~_Mask();
}

return *this;
}
#endif // _HAS_CXX23

_CONSTEXPR20 void flip() noexcept {
*const_cast<_Vbase*>(_Getptr()) ^= _Mask();
}
Expand Down
36 changes: 36 additions & 0 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -2117,12 +2117,23 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al) no
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty1&& _Val1, _Uty2&& _Val2) noexcept;

#if _HAS_CXX23
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pair<_Uty1, _Uty2>& _Pair) noexcept;
#endif // _HAS_CXX23

template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, const pair<_Uty1, _Uty2>& _Pair) noexcept;

template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pair<_Uty1, _Uty2>&& _Pair) noexcept;

#if _HAS_CXX23
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(
const _Alloc& _Al, const pair<_Uty1, _Uty2>&& _Pair) noexcept;
#endif // _HAS_CXX23

template <class _Ty, class _Alloc, class _Uty,
enable_if_t<_Is_specialization_v<_Ty, pair> && !_Is_deducible_as_pair<_Uty&>, int> = 0>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty&& _Ux) noexcept;
Expand Down Expand Up @@ -2163,6 +2174,18 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _U
_STD uses_allocator_construction_args<typename _Ty::second_type>(_Al, _STD forward<_Uty2>(_Val2)));
}

#if _HAS_CXX23
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int>>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pair<_Uty1, _Uty2>& _Pair) noexcept {
// equivalent to
// return _STD uses_allocator_construction_args<_Ty>(_Al, piecewise_construct,
// _STD forward_as_tuple(_Pair.first), _STD forward_as_tuple(_Pair.second));
return _STD make_tuple(piecewise_construct,
_STD uses_allocator_construction_args<typename _Ty::first_type>(_Al, _Pair.first),
_STD uses_allocator_construction_args<typename _Ty::second_type>(_Al, _Pair.second));
}
#endif // _HAS_CXX23

template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int>>
_NODISCARD constexpr auto uses_allocator_construction_args(
const _Alloc& _Al, const pair<_Uty1, _Uty2>& _Pair) noexcept {
Expand All @@ -2184,6 +2207,19 @@ _NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, pa
_STD uses_allocator_construction_args<typename _Ty::second_type>(_Al, _STD get<1>(_STD move(_Pair))));
}

#if _HAS_CXX23
template <class _Ty, class _Alloc, class _Uty1, class _Uty2, enable_if_t<_Is_specialization_v<_Ty, pair>, int>>
_NODISCARD constexpr auto uses_allocator_construction_args(
const _Alloc& _Al, const pair<_Uty1, _Uty2>&& _Pair) noexcept {
// equivalent to
// return _STD uses_allocator_construction_args<_Ty>(_Al, piecewise_construct,
// _STD forward_as_tuple(_STD get<0>(_STD move(_Pair)), _STD forward_as_tuple(_STD get<1>(_STD move(_Pair)));
return _STD make_tuple(piecewise_construct,
_STD uses_allocator_construction_args<typename _Ty::first_type>(_Al, _STD get<0>(_STD move(_Pair))),
_STD uses_allocator_construction_args<typename _Ty::second_type>(_Al, _STD get<1>(_STD move(_Pair))));
}
#endif // _HAS_CXX23

template <class _Ty, class _Alloc, class _Uty,
enable_if_t<_Is_specialization_v<_Ty, pair> && !_Is_deducible_as_pair<_Uty&>, int>>
_NODISCARD constexpr auto uses_allocator_construction_args(const _Alloc& _Al, _Uty&& _Ux) noexcept {
Expand Down
2 changes: 2 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@
// P2166R1 Prohibiting basic_string And basic_string_view Construction From nullptr
// P2186R2 Removing Garbage Collection Support
// P2273R3 constexpr unique_ptr
// P2321R2 zip
// (changes to pair, tuple and vector<bool>::reference only)
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
// P2443R1 views::chunk_by

// Parallel Algorithms Notes
Expand Down
5 changes: 3 additions & 2 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,14 @@ std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp SKIPPED
# deprecate before they do.
std/utilities/meta/meta.unary/meta.unary.prop/is_literal_type.deprecated.fail.cpp FAIL

# libc++ doesn't implement P2321R2's changes to vector<bool>::reference
std/containers/sequences/vector.bool/iterator_concept_conformance.compile.pass.cpp FAIL

StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved

# *** MISSING STL FEATURES ***
# P2321R2 zip
std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp FAIL
std/language.support/support.limits/support.limits.general/utility.version.pass.cpp FAIL
std/utilities/meta/meta.trans/meta.trans.other/common_reference.compile.pass.cpp FAIL
std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp FAIL

# P1328R1 constexpr type_info::operator==()
std/language.support/support.limits/support.limits.general/typeinfo.version.pass.cpp FAIL
Expand Down
5 changes: 3 additions & 2 deletions tests/libcxx/skipped_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ utilities\format\format.functions\vformat_to.pass.cpp
utilities\format\format.functions\vformat.locale.pass.cpp
utilities\format\format.functions\vformat.pass.cpp

# libc++ doesn't implement P2321R2's changes to vector<bool>::reference
containers\sequences\vector.bool\iterator_concept_conformance.compile.pass.cpp


# *** INTERACTIONS WITH CONTEST / C1XX THAT UPSTREAM LIKELY WON'T FIX ***
# Tracked by VSO-593630 "<filesystem> Enable libcxx filesystem tests"
Expand Down Expand Up @@ -230,8 +233,6 @@ utilities\meta\meta.unary\meta.unary.prop\is_literal_type.deprecated.fail.cpp
# P2321R2 zip
language.support\support.limits\support.limits.general\tuple.version.pass.cpp
language.support\support.limits\support.limits.general\utility.version.pass.cpp
utilities\meta\meta.trans\meta.trans.other\common_reference.compile.pass.cpp
utilities\meta\meta.trans\meta.trans.other\common_type.pass.cpp

# P1328R1 constexpr type_info::operator==()
language.support\support.limits\support.limits.general\typeinfo.version.pass.cpp
Expand Down
6 changes: 6 additions & 0 deletions tests/std/tests/Dev10_500860_overloaded_address_of/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ namespace Meow {

constexpr Evil() noexcept : data(1701) {}

template <int = 0>
const Evil& operator=(const Evil&) const {
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
// provide an Evil operator= for std::tuple::swap
return *this;
}

int func() const {
return 1729;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,13 @@ constexpr bool test_P0591R4() {
using ConstAllocatorConstructArgs = tuple<const int&, const allocator<int>&>;
using MovedAllocatorArgConstructArgs = tuple<allocator_arg_t, const allocator<int>&, int&&>;
using MovedAllocatorConstructArgs = tuple<int&&, const allocator<int>&>;
using OnlyAllocatorArgConstructArgs = tuple<allocator_arg_t, const allocator<int>&>;
using OnlyAllocatorConstructArgs = tuple<const allocator<int>&>;
using DefaultConstructArgs = tuple<>;
#if _HAS_CXX23
using MovedConstAllocatorArgConstructArgs = tuple<allocator_arg_t, const allocator<int>&, const int&&>;
using MovedConstAllocatorConstructArgs = tuple<const int&&, const allocator<int>&>;
#endif // _HAS_CXX23
using OnlyAllocatorArgConstructArgs = tuple<allocator_arg_t, const allocator<int>&>;
using OnlyAllocatorConstructArgs = tuple<const allocator<int>&>;
using DefaultConstructArgs = tuple<>;

{ // non-pair overload
auto tuple1 = uses_allocator_construction_args<int>(alloc, i);
Expand Down Expand Up @@ -121,12 +125,31 @@ constexpr bool test_P0591R4() {
static_assert(is_same_v<decltype(tuple9), tuple<piecewise_construct_t, AllocatorConstructArgs, tuple<int&>>>);
}

{ // pair(const pair&) overload
{ // pair(const pair&) overload before C++23; pair(pair&) overload since C++23
auto tuple10 = uses_allocator_construction_args<pair<int, AllocatorArgConstructible>>(alloc, p);
#if _HAS_CXX23
static_assert(
is_same_v<decltype(tuple10), tuple<piecewise_construct_t, tuple<int&>, AllocatorArgConstructArgs>>);
#else // _HAS_CXX23
static_assert(is_same_v<decltype(tuple10),
tuple<piecewise_construct_t, tuple<const int&>, ConstAllocatorArgConstructArgs>>);
#endif // _HAS_CXX23

auto tuple11 = uses_allocator_construction_args<pair<AllocatorConstructible, int>>(alloc, p);
#if _HAS_CXX23
static_assert(is_same_v<decltype(tuple11), tuple<piecewise_construct_t, AllocatorConstructArgs, tuple<int&>>>);
#else // _HAS_CXX23
static_assert(
is_same_v<decltype(tuple11), tuple<piecewise_construct_t, ConstAllocatorConstructArgs, tuple<const int&>>>);
#endif // _HAS_CXX23
}

{ // pair(const pair&) overload
auto tuple10 = uses_allocator_construction_args<pair<int, AllocatorArgConstructible>>(alloc, as_const(p));
static_assert(is_same_v<decltype(tuple10),
tuple<piecewise_construct_t, tuple<const int&>, ConstAllocatorArgConstructArgs>>);

auto tuple11 = uses_allocator_construction_args<pair<AllocatorConstructible, int>>(alloc, as_const(p));
static_assert(
is_same_v<decltype(tuple11), tuple<piecewise_construct_t, ConstAllocatorConstructArgs, tuple<const int&>>>);
}
Expand All @@ -141,6 +164,18 @@ constexpr bool test_P0591R4() {
is_same_v<decltype(tuple13), tuple<piecewise_construct_t, MovedAllocatorConstructArgs, tuple<int&&>>>);
}

#if _HAS_CXX23
{ // pair(const pair&&) overload
auto tuple12 = uses_allocator_construction_args<pair<int, AllocatorArgConstructible>>(alloc, move(as_const(p)));
static_assert(is_same_v<decltype(tuple12),
tuple<piecewise_construct_t, tuple<const int&&>, MovedConstAllocatorArgConstructArgs>>);

auto tuple13 = uses_allocator_construction_args<pair<AllocatorConstructible, int>>(alloc, move(as_const(p)));
static_assert(is_same_v<decltype(tuple13),
tuple<piecewise_construct_t, MovedConstAllocatorConstructArgs, tuple<const int&&>>>);
}
#endif // _HAS_CXX23

{
auto obj1 = make_obj_using_allocator<AllocatorArgConstructible>(alloc, i);
static_assert(is_same_v<decltype(obj1), AllocatorArgConstructible>);
Expand Down
Loading