diff --git a/libcxx/include/__algorithm/ranges_inplace_merge.h b/libcxx/include/__algorithm/ranges_inplace_merge.h index 5879d0e7ef0fb..54581aff396ea 100644 --- a/libcxx/include/__algorithm/ranges_inplace_merge.h +++ b/libcxx/include/__algorithm/ranges_inplace_merge.h @@ -41,7 +41,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { struct __inplace_merge { template - _LIBCPP_HIDE_FROM_ABI static constexpr auto + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX26 auto __inplace_merge_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp&& __comp, _Proj&& __proj) { auto __last_iter = ranges::next(__middle, __last); std::__inplace_merge<_RangeAlgPolicy>( @@ -51,7 +51,7 @@ struct __inplace_merge { template _Sent, class _Comp = ranges::less, class _Proj = identity> requires sortable<_Iter, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI _Iter + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Iter operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { return __inplace_merge_impl( std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj)); @@ -59,7 +59,7 @@ struct __inplace_merge { template requires sortable, _Comp, _Proj> - _LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_iterator_t<_Range> operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const { return __inplace_merge_impl( ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj)); diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index aea24e53019cc..6ba903ad3ce1e 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -1031,13 +1031,14 @@ namespace ranges { template S, class Comp = ranges::less, class Proj = identity> requires sortable - I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // since C++20 + constexpr I // constexpr since C++26 + inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // since C++20 template requires sortable, Comp, Proj> - borrowed_iterator_t + constexpr borrowed_iterator_t // constexpr since C++26 inplace_merge(R&& r, iterator_t middle, Comp comp = {}, - Proj proj = {}); // since C++20 + Proj proj = {}); // since C++20 template S, class Proj = identity, indirect_equivalence_relation> C = ranges::equal_to> diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp index 5a8640a8fc035..ee3619e0e6bcc 100644 --- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp +++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp @@ -150,8 +150,15 @@ constexpr bool all_the_algorithms() (void)std::ranges::is_sorted(a, Less(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(first, last, Less(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(a, Less(&copies)); assert(copies == 0); - if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(&copies)); assert(copies == 0); } - if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(&copies)); assert(copies == 0); } +#if TEST_STD_VER < 26 + if (!std::is_constant_evaluated()) +#endif + { + (void)std::ranges::inplace_merge(first, mid, last, Less(&copies)); + assert(copies == 0); + (void)std::ranges::inplace_merge(a, mid, Less(&copies)); + assert(copies == 0); + } (void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(&copies)); assert(copies == 0); (void)std::ranges::lexicographical_compare(a, b, Less(&copies)); assert(copies == 0); (void)std::ranges::lower_bound(first, last, value, Less(&copies)); assert(copies == 0); @@ -223,10 +230,19 @@ constexpr bool all_the_algorithms() (void)std::ranges::sort(a, Less(&copies)); assert(copies == 0); (void)std::ranges::sort_heap(first, last, Less(&copies)); assert(copies == 0); (void)std::ranges::sort_heap(a, Less(&copies)); assert(copies == 0); - if (!std::is_constant_evaluated()) { (void)std::ranges::stable_partition(first, last, UnaryTrue(&copies)); assert(copies == 0); } - if (!std::is_constant_evaluated()) { (void)std::ranges::stable_partition(a, UnaryTrue(&copies)); assert(copies == 0); } - if (!std::is_constant_evaluated()) { (void)std::ranges::stable_sort(first, last, Less(&copies)); assert(copies == 0); } - if (!std::is_constant_evaluated()) { (void)std::ranges::stable_sort(a, Less(&copies)); assert(copies == 0); } +#if TEST_STD_VER < 26 + if (!std::is_constant_evaluated()) +#endif + { + (void)std::ranges::stable_partition(first, last, UnaryTrue(&copies)); + assert(copies == 0); + (void)std::ranges::stable_partition(a, UnaryTrue(&copies)); + assert(copies == 0); + (void)std::ranges::stable_sort(first, last, Less(&copies)); + assert(copies == 0); + (void)std::ranges::stable_sort(a, Less(&copies)); + assert(copies == 0); + } #if TEST_STD_VER > 20 (void)std::ranges::starts_with(first, last, first2, last2, Equal(&copies)); assert(copies == 0); (void)std::ranges::starts_with(a, b, Equal(&copies)); assert(copies == 0); diff --git a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp index 8cdf53c183512..1a85d1f33cf10 100644 --- a/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp +++ b/libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp @@ -147,8 +147,15 @@ constexpr bool all_the_algorithms() (void)std::ranges::is_sorted(a, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(first, last, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::is_sorted_until(a, Less(), Proj(&copies)); assert(copies == 0); - if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); } - if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies)); assert(copies == 0); } +#if TEST_STD_VER < 26 + if (!std::is_constant_evaluated()) +#endif + { + (void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies)); + assert(copies == 0); + (void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies)); + assert(copies == 0); + } (void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::lexicographical_compare(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::lower_bound(first, last, value, Less(), Proj(&copies)); assert(copies == 0); @@ -228,10 +235,19 @@ constexpr bool all_the_algorithms() (void)std::ranges::sort(a, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::sort_heap(first, last, Less(), Proj(&copies)); assert(copies == 0); (void)std::ranges::sort_heap(a, Less(), Proj(&copies)); assert(copies == 0); - if (!std::is_constant_evaluated()) { (void)std::ranges::stable_partition(first, last, UnaryTrue(), Proj(&copies)); assert(copies == 0); } - if (!std::is_constant_evaluated()) { (void)std::ranges::stable_partition(a, UnaryTrue(), Proj(&copies)); assert(copies == 0); } - if (!std::is_constant_evaluated()) { (void)std::ranges::stable_sort(first, last, Less(), Proj(&copies)); assert(copies == 0); } - if (!std::is_constant_evaluated()) { (void)std::ranges::stable_sort(a, Less(), Proj(&copies)); assert(copies == 0); } +#if TEST_STD_VER < 26 + if (!std::is_constant_evaluated()) +#endif + { + (void)std::ranges::stable_partition(first, last, UnaryTrue(), Proj(&copies)); + assert(copies == 0); + (void)std::ranges::stable_partition(a, UnaryTrue(), Proj(&copies)); + assert(copies == 0); + (void)std::ranges::stable_sort(first, last, Less(), Proj(&copies)); + assert(copies == 0); + (void)std::ranges::stable_sort(a, Less(), Proj(&copies)); + assert(copies == 0); + } #if TEST_STD_VER > 20 (void)std::ranges::starts_with(first, last, first2, last2, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0); (void)std::ranges::starts_with(a, b, Equal(), Proj(&copies), Proj(&copies)); assert(copies == 0); diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/ranges_inplace_merge.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/ranges_inplace_merge.pass.cpp index 1602490893d75..827e6c1d20868 100644 --- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/ranges_inplace_merge.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/ranges_inplace_merge.pass.cpp @@ -13,13 +13,14 @@ // template S, class Comp = ranges::less, // class Proj = identity> // requires sortable -// I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // Since C++20 +// constexpr I // constexpr since C++26 +// inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // Since C++20 // // template // requires sortable, Comp, Proj> -// borrowed_iterator_t +// constexpr borrowed_iterator_t // constexpr since C++26 // inplace_merge(R&& r, iterator_t middle, Comp comp = {}, -// Proj proj = {}); // Since C++20 +// Proj proj = {}); // Since C++20 #include #include @@ -86,7 +87,7 @@ static_assert(!HasInplaceMergeRange, int*, ComparatorNotCopyable>) static_assert(!HasInplaceMergeIter, const int*>); template class SentWrapper, std::size_t N1, std::size_t N2> -void testInplaceMergeImpl(std::array input, int midIdx, std::array expected) { +TEST_CONSTEXPR_CXX26 void testInplaceMergeImpl(std::array input, int midIdx, std::array expected) { assert(std::is_sorted(input.begin(), input.begin() + midIdx)); assert(std::is_sorted(input.begin() + midIdx, input.end())); assert(std::is_sorted(expected.begin(), expected.end())); @@ -113,7 +114,7 @@ void testInplaceMergeImpl(std::array input, int midIdx, std::array class SentWrapper> -void testImpl() { +TEST_CONSTEXPR_CXX26 void testImpl() { // sorted range { std::array in{0, 1, 5, 6, 9, 10}; @@ -193,14 +194,14 @@ void testImpl() { } template < template class SentWrapper> -void withAllPermutationsOfIter() { +TEST_CONSTEXPR_CXX26 void withAllPermutationsOfIter() { testImpl, SentWrapper>(); testImpl, SentWrapper>(); testImpl, SentWrapper>(); testImpl(); } -bool test() { +TEST_CONSTEXPR_CXX26 bool test() { withAllPermutationsOfIter(); withAllPermutationsOfIter(); @@ -334,7 +335,9 @@ bool test() { int main(int, char**) { test(); - // inplace_merge is not constexpr in the latest finished Standard (C++20) +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp b/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp index e4316095f28bf..12743a08e3192 100644 --- a/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp @@ -212,8 +212,12 @@ constexpr bool test_all() { } dangling_1st(std::ranges::partial_sort, in, mid); dangling_1st(std::ranges::nth_element, in, mid); +#if TEST_STD_VER < 26 if (!std::is_constant_evaluated()) +#endif + { dangling_1st(std::ranges::inplace_merge, in, mid); + } dangling_1st(std::ranges::make_heap, in); dangling_1st(std::ranges::push_heap, in); dangling_1st(std::ranges::pop_heap, in); diff --git a/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp b/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp index aec07e9626f73..914e31d133805 100644 --- a/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp @@ -179,8 +179,12 @@ constexpr bool test_all() { } test_mid(std::ranges::partial_sort, in, mid, &Foo::binary_pred, &Bar::val); test_mid(std::ranges::nth_element, in, mid, &Foo::binary_pred, &Bar::val); +#if TEST_STD_VER < 26 if (!std::is_constant_evaluated()) +#endif + { test_mid(std::ranges::inplace_merge, in, mid, &Foo::binary_pred, &Bar::val); + } test(std::ranges::make_heap, in, &Foo::binary_pred, &Bar::val); test(std::ranges::push_heap, in, &Foo::binary_pred, &Bar::val); test(std::ranges::pop_heap, in, &Foo::binary_pred, &Bar::val); diff --git a/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp b/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp index 675c2d114b3ac..2ed2cb54788a6 100644 --- a/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp @@ -182,8 +182,12 @@ constexpr void run_tests() { } test_mid(std::ranges::partial_sort, in, mid); test_mid(std::ranges::nth_element, in, mid); +#if TEST_STD_VER < 26 if (!std::is_constant_evaluated()) +#endif + { test_mid(std::ranges::inplace_merge, in, mid); + } test(std::ranges::make_heap, in); test(std::ranges::push_heap, in); test(std::ranges::pop_heap, in); diff --git a/libcxx/test/std/algorithms/robust_against_adl_on_new.pass.cpp b/libcxx/test/std/algorithms/robust_against_adl_on_new.pass.cpp index 6bd2abded2463..32154f9eda8f6 100644 --- a/libcxx/test/std/algorithms/robust_against_adl_on_new.pass.cpp +++ b/libcxx/test/std/algorithms/robust_against_adl_on_new.pass.cpp @@ -15,23 +15,36 @@ struct A { int i = 0; - bool operator<(const A& rhs) const { return i < rhs.i; } - static bool isEven(const A& a) { return a.i % 2 == 0; } + TEST_CONSTEXPR bool operator<(const A& rhs) const { return i < rhs.i; } + static TEST_CONSTEXPR bool isEven(const A& a) { return a.i % 2 == 0; } }; void *operator new(std::size_t, A*) = delete; -int main(int, char**) -{ - A a[4] = {}; - std::sort(a, a+4); - std::sort(a, a+4, std::less()); - std::partition(a, a+4, A::isEven); - std::stable_sort(a, a+4); - std::stable_sort(a, a+4, std::less()); - std::stable_partition(a, a+4, A::isEven); - std::inplace_merge(a, a+2, a+4); - std::inplace_merge(a, a+2, a+4, std::less()); - - return 0; +TEST_CONSTEXPR_CXX20 bool test() { + A a[4] = {}; + std::sort(a, a + 4); + std::sort(a, a + 4, std::less()); + std::partition(a, a + 4, A::isEven); +#if TEST_STD_VER < 26 + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + { + std::stable_sort(a, a + 4); + std::stable_sort(a, a + 4, std::less()); + std::stable_partition(a, a + 4, A::isEven); + std::inplace_merge(a, a + 2, a + 4); + std::inplace_merge(a, a + 2, a + 4, std::less()); + } + + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER >= 20 + static_assert(test()); +#endif + + return 0; }