-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++] Implement part of P2562R1: constexpr std::inplace_merge
#129008
Open
frederick-vs-ja
wants to merge
1
commit into
llvm:main
Choose a base branch
from
frederick-vs-ja:constexpr-std-inplace_merge
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
[libc++] Implement part of P2562R1: constexpr std::inplace_merge
#129008
frederick-vs-ja
wants to merge
1
commit into
llvm:main
from
frederick-vs-ja:constexpr-std-inplace_merge
+332
−207
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-libcxx Author: A. Jiang (frederick-vs-ja) ChangesFixes #119398. Patch is 22.96 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/129008.diff 6 Files Affected:
diff --git a/libcxx/include/__algorithm/inplace_merge.h b/libcxx/include/__algorithm/inplace_merge.h
index 1fc31b66f4bd6..ca49196320981 100644
--- a/libcxx/include/__algorithm/inplace_merge.h
+++ b/libcxx/include/__algorithm/inplace_merge.h
@@ -203,7 +203,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __inplace_merge(
}
template <class _AlgPolicy, class _BidirectionalIterator, class _Compare>
-_LIBCPP_HIDE_FROM_ABI void __inplace_merge(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __inplace_merge(
_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare&& __comp) {
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
@@ -223,14 +223,14 @@ _LIBCPP_HIDE_FROM_ABI void __inplace_merge(
}
template <class _BidirectionalIterator, class _Compare>
-inline _LIBCPP_HIDE_FROM_ABI void inplace_merge(
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX26 void inplace_merge(
_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) {
std::__inplace_merge<_ClassicAlgPolicy>(
std::move(__first), std::move(__middle), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp));
}
template <class _BidirectionalIterator>
-inline _LIBCPP_HIDE_FROM_ABI void
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) {
std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less<>());
}
diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm
index 7b4cb8e496196..916d162c9fa86 100644
--- a/libcxx/include/algorithm
+++ b/libcxx/include/algorithm
@@ -1606,11 +1606,11 @@ template <class InputIterator1, class InputIterator2, class OutputIterator, clas
InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp);
template <class BidirectionalIterator>
- void
+ constexpr void // constexpr in C++26
inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last);
template <class BidirectionalIterator, class Compare>
- void
+ constexpr void // constexpr in C++26
inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp);
template <class InputIterator1, class InputIterator2>
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp
index 87bf9dc3854b3..21ade1d9fcfeb 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge.pass.cpp
@@ -8,11 +8,9 @@
// <algorithm>
-// template<BidirectionalIterator Iter>
-// requires ShuffleIterator<Iter>
-// && LessThanComparable<Iter::value_type>
-// void
-// inplace_merge(Iter first, Iter middle, Iter last);
+// template<class BidirectionalIterator>
+// constexpr void // constexpr since C++26
+// inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last);
#include <algorithm>
#include <cassert>
@@ -25,99 +23,142 @@
#if TEST_STD_VER >= 11
struct S {
- S() : i_(0) {}
- S(int i) : i_(i) {}
+ TEST_CONSTEXPR_CXX26 S() : i_(0) {}
+ TEST_CONSTEXPR_CXX26 S(int i) : i_(i) {}
+
+ TEST_CONSTEXPR_CXX26 S(const S& rhs) : i_(rhs.i_) {}
+ TEST_CONSTEXPR_CXX26 S(S&& rhs) : i_(rhs.i_) { rhs.i_ = -1; }
+
+ TEST_CONSTEXPR_CXX26 S& operator=(const S& rhs) {
+ i_ = rhs.i_;
+ return *this;
+ }
+ TEST_CONSTEXPR_CXX26 S& operator=(S&& rhs) {
+ i_ = rhs.i_;
+ rhs.i_ = -2;
+ assert(this != &rhs);
+ return *this;
+ }
+ TEST_CONSTEXPR_CXX26 S& operator=(int i) {
+ i_ = i;
+ return *this;
+ }
+
+ TEST_CONSTEXPR_CXX26 bool operator<(const S& rhs) const { return i_ < rhs.i_; }
+ TEST_CONSTEXPR_CXX26 bool operator==(const S& rhs) const { return i_ == rhs.i_; }
+ TEST_CONSTEXPR_CXX26 bool operator==(int i) const { return i_ == i; }
+
+ TEST_CONSTEXPR_CXX26 void set(int i) { i_ = i; }
+
+ int i_;
+};
+#endif // TEST_STD_VER >= 11
- S(const S& rhs) : i_(rhs.i_) {}
- S( S&& rhs) : i_(rhs.i_) { rhs.i_ = -1; }
-
- S& operator =(const S& rhs) { i_ = rhs.i_; return *this; }
- S& operator =( S&& rhs) { i_ = rhs.i_; rhs.i_ = -2; assert(this != &rhs); return *this; }
- S& operator =(int i) { i_ = i; return *this; }
-
- bool operator <(const S& rhs) const { return i_ < rhs.i_; }
- bool operator ==(const S& rhs) const { return i_ == rhs.i_; }
- bool operator ==(int i) const { return i_ == i; }
-
- void set(int i) { i_ = i; }
+std::mt19937 randomness;
- int i_;
- };
-#endif
+template <class Iter>
+void test_one_randomized(unsigned N, unsigned M) {
+ typedef typename std::iterator_traits<Iter>::value_type value_type;
+ value_type* ia = new value_type[N];
+
+ for (unsigned i = 0; i < N; ++i)
+ ia[i] = i;
+ std::shuffle(ia, ia + N, randomness);
+ std::sort(ia, ia + M);
+ std::sort(ia + M, ia + N);
+ std::inplace_merge(Iter(ia), Iter(ia + M), Iter(ia + N));
+ if (N > 0) {
+ assert(ia[0] == 0);
+ assert(ia[N - 1] == static_cast<value_type>(N - 1));
+ assert(std::is_sorted(ia, ia + N));
+ }
+ delete[] ia;
+}
-std::mt19937 randomness;
+template <class Iter>
+TEST_CONSTEXPR_CXX26 void test_one_non_randomized(unsigned N, unsigned M) {
+ typedef typename std::iterator_traits<Iter>::value_type value_type;
+ value_type* ia = new value_type[N];
+ const unsigned long small_prime = 19937;
+ const unsigned long large_prime = 212987;
+ unsigned long product_mod = small_prime;
+ for (unsigned i = 0; i < N; ++i) {
+ ia[i] = static_cast<int>(product_mod);
+ product_mod = product_mod * small_prime % large_prime;
+ }
+ std::sort(ia, ia + M);
+ std::sort(ia + M, ia + N);
+ std::inplace_merge(Iter(ia), Iter(ia + M), Iter(ia + N));
+ if (N > 0) {
+ assert(std::is_sorted(ia, ia + N));
+ }
+ delete[] ia;
+}
template <class Iter>
-void
-test_one(unsigned N, unsigned M)
-{
- typedef typename std::iterator_traits<Iter>::value_type value_type;
- assert(M <= N);
- value_type* ia = new value_type[N];
- for (unsigned i = 0; i < N; ++i)
- ia[i] = i;
- std::shuffle(ia, ia+N, randomness);
- std::sort(ia, ia+M);
- std::sort(ia+M, ia+N);
- std::inplace_merge(Iter(ia), Iter(ia+M), Iter(ia+N));
- if(N > 0)
- {
- assert(ia[0] == 0);
- assert(ia[N-1] == static_cast<value_type>(N-1));
- assert(std::is_sorted(ia, ia+N));
- }
- delete [] ia;
+TEST_CONSTEXPR_CXX26 void test_one(unsigned N, unsigned M) {
+ assert(M <= N);
+ if (!TEST_IS_CONSTANT_EVALUATED) {
+ test_one_randomized<Iter>(N, M);
+ }
+ test_one_non_randomized<Iter>(N, M);
}
template <class Iter>
-void
-test(unsigned N)
-{
- test_one<Iter>(N, 0);
- test_one<Iter>(N, N/4);
- test_one<Iter>(N, N/2);
- test_one<Iter>(N, 3*N/4);
- test_one<Iter>(N, N);
+TEST_CONSTEXPR_CXX26 void test(unsigned N) {
+ test_one<Iter>(N, 0);
+ test_one<Iter>(N, N / 4);
+ test_one<Iter>(N, N / 2);
+ test_one<Iter>(N, 3 * N / 4);
+ test_one<Iter>(N, N);
}
template <class Iter>
-void
-test()
-{
- test_one<Iter>(0, 0);
- test_one<Iter>(1, 0);
- test_one<Iter>(1, 1);
- test_one<Iter>(2, 0);
- test_one<Iter>(2, 1);
- test_one<Iter>(2, 2);
- test_one<Iter>(3, 0);
- test_one<Iter>(3, 1);
- test_one<Iter>(3, 2);
- test_one<Iter>(3, 3);
- test<Iter>(4);
- test<Iter>(100);
+TEST_CONSTEXPR_CXX26 void test() {
+ test_one<Iter>(0, 0);
+ test_one<Iter>(1, 0);
+ test_one<Iter>(1, 1);
+ test_one<Iter>(2, 0);
+ test_one<Iter>(2, 1);
+ test_one<Iter>(2, 2);
+ test_one<Iter>(3, 0);
+ test_one<Iter>(3, 1);
+ test_one<Iter>(3, 2);
+ test_one<Iter>(3, 3);
+ test<Iter>(4);
+ test<Iter>(100);
+ if (!TEST_IS_CONSTANT_EVALUATED) { // avoid blowing past constant evaluation limit
test<Iter>(1000);
+ }
}
-int main(int, char**)
-{
- test<bidirectional_iterator<int*> >();
- test<random_access_iterator<int*> >();
- test<int*>();
+TEST_CONSTEXPR_CXX26 bool test() {
+ test<bidirectional_iterator<int*> >();
+ test<random_access_iterator<int*> >();
+ test<int*>();
#if TEST_STD_VER >= 11
- test<bidirectional_iterator<S*> >();
- test<random_access_iterator<S*> >();
- test<S*>();
-#endif
+ test<bidirectional_iterator<S*> >();
+ test<random_access_iterator<S*> >();
+ test<S*>();
+#endif // TEST_STD_VER >= 11
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER >= 26
+ static_assert(test());
+#endif // TEST_STD_VER >= 26
#if TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS)
- {
- std::vector<int> vec(150, 3);
- getGlobalMemCounter()->throw_after = 0;
- std::inplace_merge(vec.begin(), vec.begin() + 100, vec.end());
- assert(std::all_of(vec.begin(), vec.end(), [](int i) { return i == 3; }));
- }
+ if (!TEST_IS_CONSTANT_EVALUATED) {
+ std::vector<int> vec(150, 3);
+ getGlobalMemCounter()->throw_after = 0;
+ std::inplace_merge(vec.begin(), vec.begin() + 100, vec.end());
+ assert(std::all_of(vec.begin(), vec.end(), [](int i) { return i == 3; }));
+ }
#endif // TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS)
return 0;
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
index bcde2323ad1de..3c98c8377de21 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.merge/inplace_merge_comp.pass.cpp
@@ -8,11 +8,9 @@
// <algorithm>
-// template<BidirectionalIterator Iter, StrictWeakOrder<auto, Iter::value_type> Compare>
-// requires ShuffleIterator<Iter>
-// && CopyConstructible<Compare>
-// void
-// inplace_merge(Iter first, Iter middle, Iter last, Compare comp);
+// template<class BidirectionalIterator, class Compare>
+// constexpr void // constexpr since C++26
+// inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp);
#include <algorithm>
#include <cassert>
@@ -23,37 +21,46 @@
#include "test_macros.h"
#if TEST_STD_VER >= 11
-#include <memory>
+# include <memory>
struct indirect_less {
template <class P>
- bool operator()(const P& x, const P& y) const {
+ TEST_CONSTEXPR_CXX26 bool operator()(const P& x, const P& y) const {
return *x < *y;
}
};
struct S {
- S() : i_(0) {}
- S(int i) : i_(i) {}
+ TEST_CONSTEXPR_CXX26 S() : i_(0) {}
+ TEST_CONSTEXPR_CXX26 S(int i) : i_(i) {}
- S(const S& rhs) : i_(rhs.i_) {}
- S( S&& rhs) : i_(rhs.i_) { rhs.i_ = -1; }
+ TEST_CONSTEXPR_CXX26 S(const S& rhs) : i_(rhs.i_) {}
+ TEST_CONSTEXPR_CXX26 S(S&& rhs) : i_(rhs.i_) { rhs.i_ = -1; }
- S& operator =(const S& rhs) { i_ = rhs.i_; return *this; }
- S& operator =( S&& rhs) { i_ = rhs.i_; rhs.i_ = -2; assert(this != &rhs); return *this; }
- S& operator =(int i) { i_ = i; return *this; }
-
- bool operator <(const S& rhs) const { return i_ < rhs.i_; }
- bool operator >(const S& rhs) const { return i_ > rhs.i_; }
- bool operator ==(const S& rhs) const { return i_ == rhs.i_; }
- bool operator ==(int i) const { return i_ == i; }
-
- void set(int i) { i_ = i; }
+ TEST_CONSTEXPR_CXX26 S& operator=(const S& rhs) {
+ i_ = rhs.i_;
+ return *this;
+ }
+ TEST_CONSTEXPR_CXX26 S& operator=(S&& rhs) {
+ i_ = rhs.i_;
+ rhs.i_ = -2;
+ assert(this != &rhs);
+ return *this;
+ }
+ TEST_CONSTEXPR_CXX26 S& operator=(int i) {
+ i_ = i;
+ return *this;
+ }
- int i_;
- };
+ TEST_CONSTEXPR_CXX26 bool operator<(const S& rhs) const { return i_ < rhs.i_; }
+ TEST_CONSTEXPR_CXX26 bool operator>(const S& rhs) const { return i_ > rhs.i_; }
+ TEST_CONSTEXPR_CXX26 bool operator==(const S& rhs) const { return i_ == rhs.i_; }
+ TEST_CONSTEXPR_CXX26 bool operator==(int i) const { return i_ == i; }
+ TEST_CONSTEXPR_CXX26 void set(int i) { i_ = i; }
+ int i_;
+};
#endif // TEST_STD_VER >= 11
#include "test_iterators.h"
@@ -62,114 +69,173 @@ struct S {
std::mt19937 randomness;
template <class Iter>
-void
-test_one(unsigned N, unsigned M)
-{
- assert(M <= N);
- typedef typename std::iterator_traits<Iter>::value_type value_type;
- value_type* ia = new value_type[N];
- for (unsigned i = 0; i < N; ++i)
- ia[i] = i;
- std::shuffle(ia, ia+N, randomness);
- std::sort(ia, ia+M, std::greater<value_type>());
- std::sort(ia+M, ia+N, std::greater<value_type>());
- binary_counting_predicate<std::greater<value_type>, value_type, value_type> pred((std::greater<value_type>()));
- std::inplace_merge(Iter(ia), Iter(ia+M), Iter(ia+N), std::ref(pred));
- if(N > 0)
- {
- assert(ia[0] == static_cast<int>(N)-1);
- assert(ia[N-1] == 0);
- assert(std::is_sorted(ia, ia+N, std::greater<value_type>()));
+void test_one_randomized(unsigned N, unsigned M) {
+ typedef typename std::iterator_traits<Iter>::value_type value_type;
+
+ value_type* ia = new value_type[N];
+ for (unsigned i = 0; i < N; ++i)
+ ia[i] = i;
+ std::shuffle(ia, ia + N, randomness);
+ std::sort(ia, ia + M, std::greater<value_type>());
+ std::sort(ia + M, ia + N, std::greater<value_type>());
+ binary_counting_predicate<std::greater<value_type>, value_type, value_type> pred((std::greater<value_type>()));
+ std::inplace_merge(Iter(ia), Iter(ia + M), Iter(ia + N), std::ref(pred));
+ if (N > 0) {
+ assert(ia[0] == static_cast<int>(N) - 1);
+ assert(ia[N - 1] == 0);
+ assert(std::is_sorted(ia, ia + N, std::greater<value_type>()));
+#if defined(_LIBCPP_HARDENING_MODE) && _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_DEBUG
+ assert(pred.count() <= (N - 1));
+#endif
+ }
+ delete[] ia;
+}
+
+template <class Iter>
+TEST_CONSTEXPR_CXX26 void test_one_non_randomized(unsigned N, unsigned M) {
+ typedef typename std::iterator_traits<Iter>::value_type value_type;
+
+ value_type* ia = new value_type[N];
+ const unsigned long small_prime = 19937;
+ const unsigned long large_prime = 212987;
+ unsigned long product_mod = small_prime;
+ for (unsigned i = 0; i < N; ++i) {
+ ia[i] = static_cast<int>(product_mod);
+ product_mod = product_mod * small_prime % large_prime;
+ }
+ std::sort(ia, ia + M, std::greater<value_type>());
+ std::sort(ia + M, ia + N, std::greater<value_type>());
+ binary_counting_predicate<std::greater<value_type>, value_type, value_type> pred((std::greater<value_type>()));
+ std::inplace_merge(Iter(ia), Iter(ia + M), Iter(ia + N), std::ref(pred));
+ if (N > 0) {
+ assert(std::is_sorted(ia, ia + N, std::greater<value_type>()));
#if defined(_LIBCPP_HARDENING_MODE) && _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_DEBUG
- assert(pred.count() <= (N-1));
+ assert(pred.count() <= (N - 1));
#endif
- }
- delete [] ia;
+ }
+ delete[] ia;
+}
+
+template <class Iter>
+TEST_CONSTEXPR_CXX26 void test_one(unsigned N, unsigned M) {
+ assert(M <= N);
+ if (!TEST_IS_CONSTANT_EVALUATED) {
+ test_one_randomized<Iter>(N, M);
+ }
+ test_one_non_randomized<Iter>(N, M);
}
template <class Iter>
-void
-test(unsigned N)
-{
- test_one<Iter>(N, 0);
- test_one<Iter>(N, N/4);
- test_one<Iter>(N, N/2);
- test_one<Iter>(N, 3*N/4);
- test_one<Iter>(N, N);
+TEST_CONSTEXPR_CXX26 void test(unsigned N) {
+ test_one<Iter>(N, 0);
+ test_one<Iter>(N, N / 4);
+ test_one<Iter>(N, N / 2);
+ test_one<Iter>(N, 3 * N / 4);
+ test_one<Iter>(N, N);
}
template <class Iter>
-void
-test()
-{
- test_one<Iter>(0, 0);
- test_one<Iter>(1, 0);
- test_one<Iter>(1, 1);
- test_one<Iter>(2, 0);
- test_one<Iter>(2, 1);
- test_one<Iter>(2, 2);
- test_one<Iter>(3, 0);
- test_one<Iter>(3, 1);
- test_one<Iter>(3, 2);
- test_one<Iter>(3, 3);
- test<Iter>(4);
- test<Iter>(20);
- test<Iter>(100);
+TEST_CONSTEXPR_CXX26 void test() {
+ test_one<Iter>(0, 0);
+ test_one<Iter>(1, 0);
+ test_one<Iter>(1, 1);
+ test_one<Iter>(2, 0);
+ test_one<Iter>(2, 1);
+ test_one<Iter>(2, 2);
+ test_one<Iter>(3, 0);
+ test_one<Iter>(3, 1);
+ test_one<Iter>(3, 2);
+ test_one<Iter>(3, 3);
+ test<Iter>(4);
+ test<Iter>(20);
+ test<Iter>(100);
+ if (!TEST_IS_CONSTANT_EVALUATED) { // avoid blowing past constant evaluation limit
test<Iter>(1000);
+ }
}
struct less_by_first {
template <typename Pair>
- bool operator()(const Pair& lhs, const Pair& rhs) const {
+ TEST_CONSTEXPR_CXX26 bool operator()(const Pair& lhs, const Pair& rhs) const {
return std::less<typename Pair::first_type>()(lhs.first, rhs.first);
}
};
-void test_PR31166 ()
-{
- typedef std::pair<int, int> P;
- typedef std::vector<P> V;
- P vec[5] = {P(1, 0), P(2, 0), P(2, 1), P(2, 2), P(2, 3)};
- for ( int i = 0; i < 5; ++i ) {
- V res(vec, vec + 5);
- std::inplace_merge(res.begin(), res.begin() + i, res.end(), less_by_first());
- assert(res.size() == 5);
- assert(std::equal(res.begin(), res.end(), vec));
- }
+TEST_CONSTEXPR_CXX26 void test_PR31166() {
+ typedef std::pair<int, int> P;
+ typedef std::vector<P> V;
+ P vec[5] = {P(1, 0), P(2, 0), P(2, 1), P(2, 2), P(2, 3)};
+ for (int i = 0; i < 5; ++i) {
+ V res(vec, vec + 5);
+ std::inplace_merge(res.begin(), res.begin() + i, res.end(), less_by_first());
+ assert(res.size() == 5);
+ assert(std::equal(res.begin(), res.end(), vec));
+ }
}
-int main(int, char**)
-{
- test<bidirectional_iterator<int*> >();
- test<random_access_iterator<int*> >();
- test<int*>();
+#if TEST_STD_VER >= 11
+void test_wrapped_randomized(int N, unsigned M) {
+ std::unique_ptr<int>* ia = new std::unique_ptr<int>[N];
+ for (int i = 0; i < N; ++i)
+ ia[i].reset(new int(i));
+ std::shuffle(ia, ia + N, randomness);
+ std::sort(ia, ia + M, indirect_less());
+ std::sort(ia + M, ia + N, indirect_less());
+ std::inplace_merge(ia, ia + M, ia + N, indirect_less());
+ if (N > 0) {
+ assert(*ia[0] == 0);
+ assert(*ia[N - 1] == N - 1);
+ assert(std::is_sorted(ia, ia + N, indirect_less()));
+ }
+ delete[] ia;
+}
+
+TEST_CONSTEXPR_CXX26 void test_wrapped_non_randomized(int N, unsigned M) {
+ std::unique_ptr<int>* ia = new std::unique_ptr<int>[N];
+
+ const unsigned long small_prime = 19937;
+ const unsigned long large_prime = 212987;
+ unsigned long product_mod = small_prime;
+ for (unsigned i = 0; i < N; ++i) {
+ ia[i].reset(new int(static_cast<int>(product_mod)));
+ product_mod = product_mod * small_prime % large_prime;
+ }
+ std::sort(ia, ia + M, indirect_less());
+ std::sort(ia + M, ia + N, indirect_less());
+ std::inplace_merge(ia, ia + M, ia + N, indirect_less());
+ if (N > 0) {
+ assert(std::is_sorted(ia, ia + N, indirect_less()));
+ }
+ delete[] ia;
+}
+#endif // TEST_STD_VER >= 11
+
+TEST_CONSTEXPR_CXX26 bool test() {
+ test<bidirectional_iterator<int*> >();
+ test<random_access_iterator<int*> >();
+ test<int*>();
#if TEST_STD_VER >= 11
- test<bidirectional_iterator<S*> >();
- test<random_access_iterator<S*> >();
- test<S*>();
-
- {
- int N = 100;
- unsigned M = 50;
- std::unique_ptr<int>* ia = new std::unique_ptr<int>[N];
- for (int i = 0; i < N; ++i)
- ia[i].reset(new int(i));
- std::shuffle(ia, ia+N, randomness);
- std::sort(ia, ia+M, indirect_less());
- std::sort(ia+M, ia+N, indirect_less());
- std::inplace_merge(ia, ia+M, ia+N, indirect_less());
- if(N > 0)
- {
- assert(*ia[0] == 0);
- assert(*ia[N-1] == N-1);
- assert(std::is_sorted(ia, ia+N, indirect_less()));
- }
- delete [] ia;
- }
+ test<bidirectional_iterator<S*> >();
+ test<random_access_iterator<S*> >();
+ test<S*>();
+
+ if (!TEST_IS_CONSTANT_EVALUATED)...
[truncated]
|
10c2e0d
to
975e7ad
Compare
975e7ad
to
df9720b
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #119398.