diff --git a/libcxx/include/__algorithm/stable_partition.h b/libcxx/include/__algorithm/stable_partition.h index 2ba7239a3a039..b389ae2508c6e 100644 --- a/libcxx/include/__algorithm/stable_partition.h +++ b/libcxx/include/__algorithm/stable_partition.h @@ -16,6 +16,7 @@ #include <__iterator/advance.h> #include <__iterator/distance.h> #include <__iterator/iterator_traits.h> +#include <__memory/construct_at.h> #include <__memory/destruct_n.h> #include <__memory/unique_ptr.h> #include <__memory/unique_temporary_buffer.h> @@ -33,7 +34,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -_LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition_impl( _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, @@ -61,7 +62,7 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl( // Move the falses into the temporary buffer, and the trues to the front of the line // Update __first to always point to the end of the trues value_type* __t = __p.first; - ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); + std::__construct_at(__t, _Ops::__iter_move(__first)); __d.template __incr(); ++__t; _ForwardIterator __i = __first; @@ -70,7 +71,7 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl( *__first = _Ops::__iter_move(__i); ++__first; } else { - ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); + std::__construct_at(__t, _Ops::__iter_move(__i)); __d.template __incr(); ++__t; } @@ -116,7 +117,7 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl( } template -_LIBCPP_HIDE_FROM_ABI _ForwardIterator +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) { typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type; typedef typename iterator_traits<_ForwardIterator>::value_type value_type; @@ -145,7 +146,7 @@ __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Pred } template -_BidirectionalIterator __stable_partition_impl( +_LIBCPP_CONSTEXPR_SINCE_CXX26 _BidirectionalIterator __stable_partition_impl( _BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, @@ -179,7 +180,7 @@ _BidirectionalIterator __stable_partition_impl( // Move the falses into the temporary buffer, and the trues to the front of the line // Update __first to always point to the end of the trues value_type* __t = __p.first; - ::new ((void*)__t) value_type(_Ops::__iter_move(__first)); + std::__construct_at(__t, _Ops::__iter_move(__first)); __d.template __incr(); ++__t; _BidirectionalIterator __i = __first; @@ -188,7 +189,7 @@ _BidirectionalIterator __stable_partition_impl( *__first = _Ops::__iter_move(__i); ++__first; } else { - ::new ((void*)__t) value_type(_Ops::__iter_move(__i)); + std::__construct_at(__t, _Ops::__iter_move(__i)); __d.template __incr(); ++__t; } @@ -247,7 +248,7 @@ _BidirectionalIterator __stable_partition_impl( } template -_LIBCPP_HIDE_FROM_ABI _BidirectionalIterator __stable_partition_impl( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _BidirectionalIterator __stable_partition_impl( _BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, bidirectional_iterator_tag) { typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type; typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; @@ -283,14 +284,14 @@ _LIBCPP_HIDE_FROM_ABI _BidirectionalIterator __stable_partition_impl( } template -_LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition( +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition( _ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) { return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>( std::move(__first), std::move(__last), __pred, __iter_category); } template -inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator +_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) { using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category; return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>( diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index 7b4cb8e496196..0c7cea11d1a91 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -1498,7 +1498,7 @@ template - ForwardIterator + constexpr ForwardIterator // constexpr in C++26 stable_partition(ForwardIterator first, ForwardIterator last, Predicate pred); template diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/stable_partition.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/stable_partition.pass.cpp index 44027543aaf16..ed55a41e83938 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/stable_partition.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/stable_partition.pass.cpp @@ -11,7 +11,7 @@ // template Pred> // requires ShuffleIterator // && CopyConstructible -// Iter +// constexpr Iter // constexpr since C++26 // stable_partition(Iter first, Iter last, Pred pred); #include @@ -23,21 +23,16 @@ #include "test_iterators.h" #include "test_macros.h" -struct is_odd -{ - bool operator()(const int& i) const {return i & 1;} +struct is_odd { + TEST_CONSTEXPR_CXX26 bool operator()(const int& i) const { return i & 1; } }; -struct odd_first -{ - bool operator()(const std::pair& p) const - {return p.first & 1;} +struct odd_first { + TEST_CONSTEXPR_CXX26 bool operator()(const std::pair& p) const { return p.first & 1; } }; template -void -test() -{ +TEST_CONSTEXPR_CXX26 void test() { { // check mixed typedef std::pair P; P array[] = @@ -282,10 +277,10 @@ test() assert(array[9] == P(0, 2)); } #if TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS) - // TODO: Re-enable this test once we get recursive inlining fixed. + // TODO: Re-enable this test for GCC once we get recursive inlining fixed. // For now it trips up GCC due to the use of always_inline. -# if 0 - { // check that the algorithm still works when no memory is available +# if !defined(TEST_COMPILER_GCC) + if (!TEST_IS_CONSTANT_EVALUATED) { // check that the algorithm still works when no memory is available std::vector vec(150, 3); vec[5] = 6; getGlobalMemCounter()->throw_after = 0; @@ -300,38 +295,45 @@ test() assert(std::is_partitioned(vec.begin(), vec.end(), [](int i) { return i < 5; })); getGlobalMemCounter()->reset(); } -# endif -#endif // TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS) +# endif // !defined(TEST_COMPILER_GCC) +#endif // TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS) } #if TEST_STD_VER >= 11 -struct is_null -{ - template - bool operator()(const P& p) {return p == 0;} +struct is_null { + template + TEST_CONSTEXPR_CXX26 bool operator()(const P& p) { + return p == 0; + } }; template -void -test1() -{ - const unsigned size = 5; - std::unique_ptr array[size]; - Iter r = std::stable_partition(Iter(array), Iter(array+size), is_null()); - assert(r == Iter(array+size)); +TEST_CONSTEXPR_CXX26 void test1() { + const unsigned size = 5; + std::unique_ptr array[size]; + Iter r = std::stable_partition(Iter(array), Iter(array + size), is_null()); + assert(r == Iter(array + size)); } #endif // TEST_STD_VER >= 11 -int main(int, char**) -{ - test*> >(); - test*> >(); - test*>(); +TEST_CONSTEXPR_CXX26 bool test() { + test*> >(); + test*> >(); + test*>(); #if TEST_STD_VER >= 11 - test1*> >(); + test1*> >(); +#endif + + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER >= 26 + static_assert(test()); #endif return 0; diff --git a/libcxx/test/std/algorithms/robust_against_proxy_iterators_lifetime_bugs.pass.cpp b/libcxx/test/std/algorithms/robust_against_proxy_iterators_lifetime_bugs.pass.cpp index c89d6f5a229e8..e00f123538df8 100644 --- a/libcxx/test/std/algorithms/robust_against_proxy_iterators_lifetime_bugs.pass.cpp +++ b/libcxx/test/std/algorithms/robust_against_proxy_iterators_lifetime_bugs.pass.cpp @@ -735,12 +735,20 @@ TEST_CONSTEXPR_CXX20 bool test() { test(simple_in, [&](I b, I e) { (void) std::shuffle(b, e, rand_gen()); }); // TODO: unique test(simple_in, [&](I b, I e) { (void) std::partition(b, e, is_neg); }); +#if TEST_STD_VER < 26 if (!TEST_IS_CONSTANT_EVALUATED) - test(simple_in, [&](I b, I e) { (void) std::stable_partition(b, e, is_neg); }); +#endif + { + test(simple_in, [&](I b, I e) { (void)std::stable_partition(b, e, is_neg); }); + } if (!TEST_IS_CONSTANT_EVALUATED) - test(sort_test_in, [&](I b, I e) { (void) std::sort(b, e); }); + test(sort_test_in, [&](I b, I e) { (void)std::sort(b, e); }); +#if TEST_STD_VER < 26 if (!TEST_IS_CONSTANT_EVALUATED) - test(sort_test_in, [&](I b, I e) { (void) std::stable_sort(b, e); }); +#endif + { + test(sort_test_in, [&](I b, I e) { (void)std::stable_sort(b, e); }); + } // TODO: partial_sort // TODO: nth_element // TODO: inplace_merge diff --git a/libcxx/test/std/algorithms/robust_re_difference_type.compile.pass.cpp b/libcxx/test/std/algorithms/robust_re_difference_type.compile.pass.cpp index 7d6be48430179..187113b0bdeae 100644 --- a/libcxx/test/std/algorithms/robust_re_difference_type.compile.pass.cpp +++ b/libcxx/test/std/algorithms/robust_re_difference_type.compile.pass.cpp @@ -240,9 +240,14 @@ TEST_CONSTEXPR_CXX20 bool all_the_algorithms() (void)std::sort(first, last, std::less()); (void)std::sort_heap(first, last); (void)std::sort_heap(first, last, std::less()); - if (!TEST_IS_CONSTANT_EVALUATED) (void)std::stable_partition(first, last, UnaryTrue()); - if (!TEST_IS_CONSTANT_EVALUATED) (void)std::stable_sort(first, last); - if (!TEST_IS_CONSTANT_EVALUATED) (void)std::stable_sort(first, last, std::less()); +#if TEST_STD_VER < 26 + if (!TEST_IS_CONSTANT_EVALUATED) +#endif + { + (void)std::stable_partition(first, last, UnaryTrue()); + (void)std::stable_sort(first, last); + (void)std::stable_sort(first, last, std::less()); + } (void)std::swap_ranges(first, last, first2); (void)std::transform(first, last, first2, UnaryTransform()); (void)std::transform(first, mid, mid, first2, BinaryTransform());