Skip to content

Commit b18b399

Browse files
[libc++] Implement constexpr ranges::inplace_merge
1 parent ecae8d0 commit b18b399

File tree

8 files changed

+47
-17
lines changed

8 files changed

+47
-17
lines changed

libcxx/include/__algorithm/ranges_inplace_merge.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,15 @@ struct __inplace_merge {
5151

5252
template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity>
5353
requires sortable<_Iter, _Comp, _Proj>
54-
_LIBCPP_HIDE_FROM_ABI _Iter
54+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Iter
5555
operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
5656
return __inplace_merge_impl(
5757
std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj));
5858
}
5959

6060
template <bidirectional_range _Range, class _Comp = ranges::less, class _Proj = identity>
6161
requires sortable<iterator_t<_Range>, _Comp, _Proj>
62-
_LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range>
62+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_iterator_t<_Range>
6363
operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const {
6464
return __inplace_merge_impl(
6565
ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj));

libcxx/include/algorithm

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,13 +1031,14 @@ namespace ranges {
10311031
template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less,
10321032
class Proj = identity>
10331033
requires sortable<I, Comp, Proj>
1034-
I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // since C++20
1034+
constexpr I // constexpr since C++26
1035+
inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // since C++20
10351036
10361037
template<bidirectional_range R, class Comp = ranges::less, class Proj = identity>
10371038
requires sortable<iterator_t<R>, Comp, Proj>
1038-
borrowed_iterator_t<R>
1039+
constexpr borrowed_iterator_t<R> // constexpr since C++26
10391040
inplace_merge(R&& r, iterator_t<R> middle, Comp comp = {},
1040-
Proj proj = {}); // since C++20
1041+
Proj proj = {}); // since C++20
10411042
10421043
template<permutable I, sentinel_for<I> S, class Proj = identity,
10431044
indirect_equivalence_relation<projected<I, Proj>> C = ranges::equal_to>

libcxx/test/libcxx/algorithms/ranges_robust_against_copying_comparators.pass.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,15 @@ constexpr bool all_the_algorithms()
150150
(void)std::ranges::is_sorted(a, Less(&copies)); assert(copies == 0);
151151
(void)std::ranges::is_sorted_until(first, last, Less(&copies)); assert(copies == 0);
152152
(void)std::ranges::is_sorted_until(a, Less(&copies)); assert(copies == 0);
153-
if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(&copies)); assert(copies == 0); }
154-
if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(&copies)); assert(copies == 0); }
153+
#if TEST_STD_VER < 26
154+
if (!std::is_constant_evaluated())
155+
#endif
156+
{
157+
(void)std::ranges::inplace_merge(first, mid, last, Less(&copies));
158+
assert(copies == 0);
159+
(void)std::ranges::inplace_merge(a, mid, Less(&copies));
160+
assert(copies == 0);
161+
}
155162
(void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(&copies)); assert(copies == 0);
156163
(void)std::ranges::lexicographical_compare(a, b, Less(&copies)); assert(copies == 0);
157164
(void)std::ranges::lower_bound(first, last, value, Less(&copies)); assert(copies == 0);

libcxx/test/libcxx/algorithms/ranges_robust_against_copying_projections.pass.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,15 @@ constexpr bool all_the_algorithms()
147147
(void)std::ranges::is_sorted(a, Less(), Proj(&copies)); assert(copies == 0);
148148
(void)std::ranges::is_sorted_until(first, last, Less(), Proj(&copies)); assert(copies == 0);
149149
(void)std::ranges::is_sorted_until(a, Less(), Proj(&copies)); assert(copies == 0);
150-
if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies)); assert(copies == 0); }
151-
if (!std::is_constant_evaluated()) { (void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies)); assert(copies == 0); }
150+
#if TEST_STD_VER < 26
151+
if (!std::is_constant_evaluated())
152+
#endif
153+
{
154+
(void)std::ranges::inplace_merge(first, mid, last, Less(), Proj(&copies));
155+
assert(copies == 0);
156+
(void)std::ranges::inplace_merge(a, mid, Less(), Proj(&copies));
157+
assert(copies == 0);
158+
}
152159
(void)std::ranges::lexicographical_compare(first, last, first2, last2, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
153160
(void)std::ranges::lexicographical_compare(a, b, Less(), Proj(&copies), Proj(&copies)); assert(copies == 0);
154161
(void)std::ranges::lower_bound(first, last, value, Less(), Proj(&copies)); assert(copies == 0);

libcxx/test/std/algorithms/alg.sorting/alg.merge/ranges_inplace_merge.pass.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313
// template<bidirectional_iterator I, sentinel_for<I> S, class Comp = ranges::less,
1414
// class Proj = identity>
1515
// requires sortable<I, Comp, Proj>
16-
// I inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // Since C++20
16+
// constexpr I // constexpr since C++26
17+
// inplace_merge(I first, I middle, S last, Comp comp = {}, Proj proj = {}); // Since C++20
1718
//
1819
// template<bidirectional_range R, class Comp = ranges::less, class Proj = identity>
1920
// requires sortable<iterator_t<R>, Comp, Proj>
20-
// borrowed_iterator_t<R>
21+
// constexpr borrowed_iterator_t<R> // constexpr since C++26
2122
// inplace_merge(R&& r, iterator_t<R> middle, Comp comp = {},
22-
// Proj proj = {}); // Since C++20
23+
// Proj proj = {}); // Since C++20
2324

2425
#include <algorithm>
2526
#include <array>
@@ -86,7 +87,7 @@ static_assert(!HasInplaceMergeRange<R<int*>, int*, ComparatorNotCopyable<int*>>)
8687
static_assert(!HasInplaceMergeIter<R<const int*>, const int*>);
8788

8889
template <class In, template <class> class SentWrapper, std::size_t N1, std::size_t N2>
89-
void testInplaceMergeImpl(std::array<int, N1> input, int midIdx, std::array<int, N2> expected) {
90+
TEST_CONSTEXPR_CXX26 void testInplaceMergeImpl(std::array<int, N1> input, int midIdx, std::array<int, N2> expected) {
9091
assert(std::is_sorted(input.begin(), input.begin() + midIdx));
9192
assert(std::is_sorted(input.begin() + midIdx, input.end()));
9293
assert(std::is_sorted(expected.begin(), expected.end()));
@@ -113,7 +114,7 @@ void testInplaceMergeImpl(std::array<int, N1> input, int midIdx, std::array<int,
113114
}
114115

115116
template <class In, template <class> class SentWrapper>
116-
void testImpl() {
117+
TEST_CONSTEXPR_CXX26 void testImpl() {
117118
// sorted range
118119
{
119120
std::array in{0, 1, 5, 6, 9, 10};
@@ -193,14 +194,14 @@ void testImpl() {
193194
}
194195

195196
template < template <class> class SentWrapper>
196-
void withAllPermutationsOfIter() {
197+
TEST_CONSTEXPR_CXX26 void withAllPermutationsOfIter() {
197198
testImpl<bidirectional_iterator<int*>, SentWrapper>();
198199
testImpl<random_access_iterator<int*>, SentWrapper>();
199200
testImpl<contiguous_iterator<int*>, SentWrapper>();
200201
testImpl<int*, SentWrapper>();
201202
}
202203

203-
bool test() {
204+
TEST_CONSTEXPR_CXX26 bool test() {
204205
withAllPermutationsOfIter<std::type_identity_t>();
205206
withAllPermutationsOfIter<sentinel_wrapper>();
206207

@@ -334,7 +335,9 @@ bool test() {
334335

335336
int main(int, char**) {
336337
test();
337-
// inplace_merge is not constexpr in the latest finished Standard (C++20)
338+
#if TEST_STD_VER >= 26
339+
static_assert(test());
340+
#endif
338341

339342
return 0;
340343
}

libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,12 @@ constexpr bool test_all() {
212212
}
213213
dangling_1st(std::ranges::partial_sort, in, mid);
214214
dangling_1st(std::ranges::nth_element, in, mid);
215+
#if TEST_STD_VER < 26
215216
if (!std::is_constant_evaluated())
217+
#endif
218+
{
216219
dangling_1st(std::ranges::inplace_merge, in, mid);
220+
}
217221
dangling_1st(std::ranges::make_heap, in);
218222
dangling_1st(std::ranges::push_heap, in);
219223
dangling_1st(std::ranges::pop_heap, in);

libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,12 @@ constexpr bool test_all() {
179179
}
180180
test_mid(std::ranges::partial_sort, in, mid, &Foo::binary_pred, &Bar::val);
181181
test_mid(std::ranges::nth_element, in, mid, &Foo::binary_pred, &Bar::val);
182+
#if TEST_STD_VER < 26
182183
if (!std::is_constant_evaluated())
184+
#endif
185+
{
183186
test_mid(std::ranges::inplace_merge, in, mid, &Foo::binary_pred, &Bar::val);
187+
}
184188
test(std::ranges::make_heap, in, &Foo::binary_pred, &Bar::val);
185189
test(std::ranges::push_heap, in, &Foo::binary_pred, &Bar::val);
186190
test(std::ranges::pop_heap, in, &Foo::binary_pred, &Bar::val);

libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,12 @@ constexpr void run_tests() {
182182
}
183183
test_mid(std::ranges::partial_sort, in, mid);
184184
test_mid(std::ranges::nth_element, in, mid);
185+
#if TEST_STD_VER < 26
185186
if (!std::is_constant_evaluated())
187+
#endif
188+
{
186189
test_mid(std::ranges::inplace_merge, in, mid);
190+
}
187191
test(std::ranges::make_heap, in);
188192
test(std::ranges::push_heap, in);
189193
test(std::ranges::pop_heap, in);

0 commit comments

Comments
 (0)