mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 19:16:43 +00:00
[libc++] Implement part of P2562R1: constexpr ranges::stable_partition
(#129839)
This commit is contained in:
parent
12c5a46c30
commit
c28c508962
@ -44,7 +44,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
namespace ranges {
|
||||
struct __stable_partition {
|
||||
template <class _Iter, class _Sent, class _Proj, class _Pred>
|
||||
_LIBCPP_HIDE_FROM_ABI static subrange<__remove_cvref_t<_Iter>>
|
||||
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX26 subrange<__remove_cvref_t<_Iter>>
|
||||
__stable_partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) {
|
||||
auto __last_iter = ranges::next(__first, __last);
|
||||
|
||||
@ -60,7 +60,8 @@ struct __stable_partition {
|
||||
class _Proj = identity,
|
||||
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
|
||||
requires permutable<_Iter>
|
||||
_LIBCPP_HIDE_FROM_ABI subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 subrange<_Iter>
|
||||
operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
|
||||
return __stable_partition_fn_impl(__first, __last, __pred, __proj);
|
||||
}
|
||||
|
||||
@ -68,7 +69,7 @@ struct __stable_partition {
|
||||
class _Proj = identity,
|
||||
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
|
||||
requires permutable<iterator_t<_Range>>
|
||||
_LIBCPP_HIDE_FROM_ABI borrowed_subrange_t<_Range>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_subrange_t<_Range>
|
||||
operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
|
||||
return __stable_partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
|
||||
}
|
||||
|
@ -627,12 +627,14 @@ namespace ranges {
|
||||
template<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity,
|
||||
indirect_unary_predicate<projected<I, Proj>> Pred>
|
||||
requires permutable<I>
|
||||
subrange<I> stable_partition(I first, S last, Pred pred, Proj proj = {}); // since C++20
|
||||
constexpr subrange<I> // constexpr since C++26
|
||||
stable_partition(I first, S last, Pred pred, Proj proj = {}); // since C++20
|
||||
|
||||
template<bidirectional_range R, class Proj = identity,
|
||||
indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
|
||||
requires permutable<iterator_t<R>>
|
||||
borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, Proj proj = {}); // since C++20
|
||||
constexpr borrowed_subrange_t<R> // constexpr since C++26
|
||||
stable_partition(R&& r, Pred pred, Proj proj = {}); // since C++20
|
||||
|
||||
template<input_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2,
|
||||
class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity>
|
||||
|
@ -13,12 +13,14 @@
|
||||
// template<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity,
|
||||
// indirect_unary_predicate<projected<I, Proj>> Pred>
|
||||
// requires permutable<I>
|
||||
// subrange<I> stable_partition(I first, S last, Pred pred, Proj proj = {}); // Since C++20
|
||||
// constexpr subrange<I> // constexpr since C++26
|
||||
// stable_partition(I first, S last, Pred pred, Proj proj = {}); // Since C++20
|
||||
//
|
||||
// template<bidirectional_range R, class Proj = identity,
|
||||
// indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
|
||||
// requires permutable<iterator_t<R>>
|
||||
// borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, Proj proj = {}); // Since C++20
|
||||
// constexpr borrowed_subrange_t<R> // constexpr since C++26
|
||||
// stable_partition(R&& r, Pred pred, Proj proj = {}); // Since C++20
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@ -85,7 +87,8 @@ static_assert(!HasStablePartitionRange<R<PermutableNotForwardIterator>, UnaryPre
|
||||
static_assert(!HasStablePartitionRange<R<PermutableNotSwappable>, UnaryPred>);
|
||||
|
||||
template <class Iter, class Sent, std::size_t N, class Pred>
|
||||
void test_one(std::array<int, N> input, Pred pred, std::size_t partition_point, std::array<int, N> expected) {
|
||||
TEST_CONSTEXPR_CXX26 void
|
||||
test_one(std::array<int, N> input, Pred pred, std::size_t partition_point, std::array<int, N> expected) {
|
||||
auto neg_pred = [&](int x) { return !pred(x); };
|
||||
|
||||
{ // (iterator, sentinel) overload.
|
||||
@ -121,7 +124,7 @@ void test_one(std::array<int, N> input, Pred pred, std::size_t partition_point,
|
||||
}
|
||||
|
||||
template <class Iter, class Sent>
|
||||
void test_iterators_2() {
|
||||
TEST_CONSTEXPR_CXX26 void test_iterators_2() {
|
||||
auto is_odd = [](int x) { return x % 2 != 0; };
|
||||
|
||||
// Empty sequence.
|
||||
@ -157,19 +160,19 @@ void test_iterators_2() {
|
||||
}
|
||||
|
||||
template <class Iter>
|
||||
void test_iterators_1() {
|
||||
TEST_CONSTEXPR_CXX26 void test_iterators_1() {
|
||||
test_iterators_2<Iter, Iter>();
|
||||
test_iterators_2<Iter, sentinel_wrapper<Iter>>();
|
||||
}
|
||||
|
||||
void test_iterators() {
|
||||
TEST_CONSTEXPR_CXX26 void test_iterators() {
|
||||
test_iterators_1<bidirectional_iterator<int*>>();
|
||||
test_iterators_1<random_access_iterator<int*>>();
|
||||
test_iterators_1<contiguous_iterator<int*>>();
|
||||
test_iterators_1<int*>();
|
||||
}
|
||||
|
||||
void test() {
|
||||
TEST_CONSTEXPR_CXX26 bool test() {
|
||||
test_iterators();
|
||||
|
||||
{ // The algorithm is stable (equivalent elements remain in the same order).
|
||||
@ -238,11 +241,15 @@ void test() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
// Note: `stable_partition` is not `constexpr`.
|
||||
#if TEST_STD_VER >= 26
|
||||
static_assert(test());
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -197,8 +197,12 @@ constexpr bool test_all() {
|
||||
dangling_1st(std::ranges::shuffle, in, rand_gen());
|
||||
dangling_1st(std::ranges::unique, in);
|
||||
dangling_1st(std::ranges::partition, in, unary_pred);
|
||||
#if TEST_STD_VER < 26
|
||||
if (!std::is_constant_evaluated())
|
||||
#endif
|
||||
{
|
||||
dangling_1st(std::ranges::stable_partition, in, unary_pred);
|
||||
}
|
||||
dangling_1st(std::ranges::sort, in);
|
||||
if (!std::is_constant_evaluated())
|
||||
dangling_1st(std::ranges::stable_sort, in);
|
||||
|
@ -164,8 +164,12 @@ constexpr bool test_all() {
|
||||
// For `shuffle`, whether the given generator is invoked via `std::invoke` is not observable.
|
||||
test(std::ranges::unique, in, &Foo::binary_pred, &Bar::val);
|
||||
test(std::ranges::partition, in, &Foo::unary_pred, &Bar::val);
|
||||
#if TEST_STD_VER < 26
|
||||
if (!std::is_constant_evaluated())
|
||||
#endif
|
||||
{
|
||||
test(std::ranges::stable_partition, in, &Foo::unary_pred, &Bar::val);
|
||||
}
|
||||
test(std::ranges::sort, in, &Foo::binary_pred, &Bar::val);
|
||||
if (!std::is_constant_evaluated())
|
||||
test(std::ranges::stable_sort, in, &Foo::binary_pred, &Bar::val);
|
||||
|
@ -167,8 +167,12 @@ constexpr void run_tests() {
|
||||
}
|
||||
test(std::ranges::unique, in);
|
||||
test(std::ranges::partition, in, unary_pred);
|
||||
#if TEST_STD_VER < 26
|
||||
if (!std::is_constant_evaluated())
|
||||
#endif
|
||||
{
|
||||
test(std::ranges::stable_partition, in, unary_pred);
|
||||
}
|
||||
test(std::ranges::sort, in);
|
||||
if (!std::is_constant_evaluated())
|
||||
test(std::ranges::stable_sort, in);
|
||||
|
Loading…
x
Reference in New Issue
Block a user