diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index 67ef35ec39b2a..8be1ff588cf3b 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -198,7 +198,7 @@ "`3629 `__","``make_error_code`` and ``make_error_condition`` are customization points","November 2022","|Complete|","16.0","" "`3636 `__","``formatter::format`` should be ``const``-qualified","November 2022","|Complete|","16.0","|format|" "`3646 `__","``std::ranges::view_interface::size`` returns a signed type","November 2022","|Complete|","16.0","|ranges|" -"`3677 `__","Is a cv-qualified ``pair`` specially handled in uses-allocator construction?", "November 2022","","","" +"`3677 `__","Is a cv-qualified ``pair`` specially handled in uses-allocator construction?", "November 2022","|Complete|","18.0","" "`3717 `__","``common_view::end`` should improve ``random_access_range`` case", "November 2022","","","|ranges|" "`3732 `__","``prepend_range`` and ``append_range`` can't be amortized constant time", "November 2022","|Nothing to do|","","|ranges|" "`3736 `__","``move_iterator`` missing ``disable_sized_sentinel_for`` specialization", "November 2022","","","|ranges|" @@ -262,7 +262,7 @@ "`3742 `__","``deque::prepend_range`` needs to permute","February 2023","","","|ranges|" "`3790 `__","`P1467 `__ accidentally changed ``nexttoward``'s signature","February 2023","","","" "`3819 `__","``reference_meows_from_temporary`` should not use ``is_meowible``","February 2023","","","" -"`3821 `__","``uses_allocator_construction_args`` should have overload for ``pair-like``","February 2023","","","" +"`3821 `__","``uses_allocator_construction_args`` should have overload for ``pair-like``","February 2023","|Complete|","18.0.0","" "`3834 `__","Missing ``constexpr`` for ``std::intmax_t`` math functions in ````","February 2023","","","" "`3839 `__","``range_formatter``'s ``set_separator``, ``set_brackets``, and ``underlying`` functions should be ``noexcept``","February 2023","|Complete|","17.0","|format|" "`3841 `__","```` should not be ""all freestanding""","February 2023","","","" diff --git a/libcxx/include/__memory/uses_allocator_construction.h b/libcxx/include/__memory/uses_allocator_construction.h index a2e4f6e26f4b3..71ae5bcd32331 100644 --- a/libcxx/include/__memory/uses_allocator_construction.h +++ b/libcxx/include/__memory/uses_allocator_construction.h @@ -12,6 +12,7 @@ #include <__config> #include <__memory/construct_at.h> #include <__memory/uses_allocator.h> +#include <__tuple/pair_like.h> #include <__type_traits/enable_if.h> #include <__type_traits/is_same.h> #include <__type_traits/remove_cv.h> @@ -36,15 +37,19 @@ inline constexpr bool __is_std_pair = false; template inline constexpr bool __is_std_pair> = true; -template , int> = 0> +template +inline constexpr bool __is_cv_std_pair = __is_std_pair>; + +template , int> = 0> _LIBCPP_HIDE_FROM_ABI constexpr auto __uses_allocator_construction_args(const _Alloc& __alloc, _Args&&... __args) noexcept { - if constexpr (!uses_allocator_v<_Type, _Alloc> && is_constructible_v<_Type, _Args...>) { + if constexpr (!uses_allocator_v, _Alloc> && is_constructible_v<_Type, _Args...>) { return std::forward_as_tuple(std::forward<_Args>(__args)...); - } else if constexpr (uses_allocator_v<_Type, _Alloc> && + } else if constexpr (uses_allocator_v, _Alloc> && is_constructible_v<_Type, allocator_arg_t, const _Alloc&, _Args...>) { return tuple(allocator_arg, __alloc, std::forward<_Args>(__args)...); - } else if constexpr (uses_allocator_v<_Type, _Alloc> && is_constructible_v<_Type, _Args..., const _Alloc&>) { + } else if constexpr (uses_allocator_v, _Alloc> && + is_constructible_v<_Type, _Args..., const _Alloc&>) { return std::forward_as_tuple(std::forward<_Args>(__args)..., __alloc); } else { static_assert( @@ -52,7 +57,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, _Args&&... __args) noe } } -template , int> = 0> +template , 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( @@ -71,12 +76,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __uses_allocator_construction_args( std::forward<_Tuple2>(__y))); } -template , int> = 0> +template , 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 , int> = 0> +template , 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>( @@ -87,7 +92,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, _Up&& __u, _Vp&& __v) } # if _LIBCPP_STD_VER >= 23 -template , int> = 0> +template , 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>( @@ -95,14 +100,14 @@ __uses_allocator_construction_args(const _Alloc& __alloc, pair<_Up, _Vp>& __pair } # endif -template , int> = 0> +template , 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 , int> = 0> +template , 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>( @@ -113,7 +118,7 @@ __uses_allocator_construction_args(const _Alloc& __alloc, pair<_Up, _Vp>&& __pai } # if _LIBCPP_STD_VER >= 23 -template , int> = 0> +template , 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>( @@ -122,6 +127,20 @@ __uses_allocator_construction_args(const _Alloc& __alloc, const pair<_Up, _Vp>&& 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 _PairLike, + __enable_if_t<__is_cv_std_pair<_Pair> && !__is_specialization_of_subrange>::value, + 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 namespace __uses_allocator_detail { @@ -139,23 +158,33 @@ template inline constexpr bool __convertible_to_const_pair_ref = decltype(__uses_allocator_detail::__convertible_to_const_pair_ref_impl<_Tp>(0))::value; +# if _LIBCPP_STD_VER >= 23 +template +inline constexpr bool __uses_allocator_constraints = + __is_cv_std_pair<_Tp> && + (__is_specialization_of_subrange>::value || + (!__pair_like<_Up> && !__convertible_to_const_pair_ref<_Up>)); +# else +template +inline constexpr bool __uses_allocator_constraints = __is_cv_std_pair<_Tp> && !__convertible_to_const_pair_ref<_Up>; +# endif + } // namespace __uses_allocator_detail -template < - class _Pair, - class _Alloc, - class _Type, - __enable_if_t<__is_std_pair<_Pair> && !__uses_allocator_detail::__convertible_to_const_pair_ref<_Type>, int> = 0> +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 _LIBCPP_HIDE_FROM_ABI constexpr _Type __make_obj_using_allocator(const _Alloc& __alloc, _Args&&... __args); -template && !__uses_allocator_detail::__convertible_to_const_pair_ref<_Type>, int>> +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 { diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h index 62dac6dd1da3f..535344eb1e2d6 100644 --- a/libcxx/include/__utility/pair.h +++ b/libcxx/include/__utility/pair.h @@ -284,7 +284,8 @@ struct _LIBCPP_TEMPLATE_VIS pair } template <__pair_like _PairLike> - requires(is_constructible_v(std::declval<_PairLike&&>()))> && + requires(!__is_specialization_of_subrange>::value && + is_constructible_v(std::declval<_PairLike&&>()))> && is_constructible_v(std::declval<_PairLike&&>()))>) _LIBCPP_HIDE_FROM_ABI constexpr explicit(__pair_like_explicit_wknd<_PairLike>()) pair(_PairLike&& __p) diff --git a/libcxx/include/memory b/libcxx/include/memory index cd6bcc7eaa35d..24ba82f43ddd3 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -867,6 +867,43 @@ template struct hash >; template inline constexpr bool uses_allocator_v = uses_allocator::value; +// [allocator.uses.construction], uses-allocator construction +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, // since C++20 + Args&&... args) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, // since C++20 + piecewise_construct_t, + Tuple1&& x, Tuple2&& y) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc) noexcept; // since C++20 +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, // since C++20 + U&& u, V&& v) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, // since C++23 + pair& pr) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, // since C++20 + const pair& pr) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, // since C++20 + pair&& pr) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, // since C++23 + const pair&& pr) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, // since C++20 + P&& p) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, // since C++20 + U&& u) noexcept; +template + constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); // since C++20 +template + constexpr T* uninitialized_construct_using_allocator(T* p, // since C++20 + const Alloc& alloc, Args&&... args); + // [ptr.align] void* align(size_t alignment, size_t size, void*& ptr, size_t& space); diff --git a/libcxx/test/std/depr/depr.numeric.imits.has.denorm/deprecated.verify.cpp b/libcxx/test/std/depr/depr.numeric.imits.has.denorm/deprecated.verify.cpp index 82f838c57f1e4..98d49de80a58c 100644 --- a/libcxx/test/std/depr/depr.numeric.imits.has.denorm/deprecated.verify.cpp +++ b/libcxx/test/std/depr/depr.numeric.imits.has.denorm/deprecated.verify.cpp @@ -91,8 +91,9 @@ void func() { std::numeric_limits::has_denorm_loss; // expected-warning {{'has_denorm_loss' is deprecated}} std::numeric_limits::denorm_min(); - std::numeric_limits::has_denorm; // expected-warning {{'has_denorm' is deprecated}} - std::numeric_limits::has_denorm_loss; // expected-warning {{'has_denorm_loss' is deprecated}} + std::numeric_limits::has_denorm; // expected-warning {{'has_denorm' is deprecated}} + std::numeric_limits< + const volatile long double>::has_denorm_loss; // expected-warning {{'has_denorm_loss' is deprecated}} std::numeric_limits::denorm_min(); std::denorm_indeterminate; // expected-warning {{'denorm_indeterminate' is deprecated}} diff --git a/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp b/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp new file mode 100644 index 0000000000000..1d0dfd05b3f7e --- /dev/null +++ b/libcxx/test/std/ranges/range.utility/range.subrange/operator.pair_like.pass.cpp @@ -0,0 +1,80 @@ + +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// template PairLike> +// requires pair-like-convertible-from +// constexpr operator PairLike() const; + +#include +#include +#include + +#include "test_macros.h" + +static_assert(std::convertible_to, std::pair>); +static_assert(std::convertible_to, std::tuple>); +static_assert(!std::convertible_to, std::pair>); +static_assert(!std::convertible_to, std::pair>); +static_assert(!std::convertible_to, std::pair>); +static_assert(!std::convertible_to, std::array>); + +constexpr bool test() { + // Check to std::pair + { + int data[] = {1, 2, 3, 4, 5}; + const std::ranges::subrange a(data); + { + std::pair p(a); + assert(p.first == data + 0); + assert(p.second == data + 5); + } + { + std::pair p{a}; + assert(p.first == data + 0); + assert(p.second == data + 5); + } + { + std::pair p = a; + assert(p.first == data + 0); + assert(p.second == data + 5); + } + } + + // Check to std::tuple + { + int data[] = {1, 2, 3, 4, 5}; + const std::ranges::subrange a(data); + { + std::tuple p(a); + assert(std::get<0>(p) == data + 0); + assert(std::get<1>(p) == data + 5); + } + { + std::tuple p{a}; + assert(std::get<0>(p) == data + 0); + assert(std::get<1>(p) == data + 5); + } + { + std::tuple p = a; + assert(std::get<0>(p) == data + 0); + assert(std::get<1>(p) == data + 5); + } + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} 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 739278e74ddab..ab3c039497dd9 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 @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -28,25 +29,27 @@ constexpr decltype(auto) test_uses_allocator_construction_args(Args&&... args) { return std::uses_allocator_construction_args(std::forward(args)...); } -constexpr bool test() { +template