8
8
9
9
// <algorithm>
10
10
11
- // template<BidirectionalIterator Iter>
12
- // requires ShuffleIterator<Iter>
13
- // && LessThanComparable<Iter::value_type>
14
- // void
15
- // inplace_merge(Iter first, Iter middle, Iter last);
11
+ // template<class BidirectionalIterator>
12
+ // constexpr void // constexpr since C++26
13
+ // inplace_merge(BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last);
16
14
17
15
#include < algorithm>
18
16
#include < cassert>
25
23
26
24
#if TEST_STD_VER >= 11
27
25
struct S {
28
- S () : i_(0 ) {}
29
- S (int i) : i_(i) {}
26
+ TEST_CONSTEXPR_CXX26 S () : i_(0 ) {}
27
+ TEST_CONSTEXPR_CXX26 S (int i) : i_(i) {}
30
28
31
- S (const S& rhs) : i_(rhs.i_) {}
32
- S ( S&& rhs) : i_(rhs.i_) { rhs.i_ = -1 ; }
29
+ TEST_CONSTEXPR_CXX26 S (const S& rhs) : i_(rhs.i_) {}
30
+ TEST_CONSTEXPR_CXX26 S ( S&& rhs) : i_(rhs.i_) { rhs.i_ = -1 ; }
33
31
34
- S& operator =(const S& rhs) { i_ = rhs.i_ ; return *this ; }
35
- S& operator =( S&& rhs) { i_ = rhs.i_ ; rhs.i_ = -2 ; assert (this != &rhs); return *this ; }
36
- S& operator =(int i) { i_ = i; return *this ; }
32
+ TEST_CONSTEXPR_CXX26 S& operator =(const S& rhs) { i_ = rhs.i_ ; return *this ; }
33
+ TEST_CONSTEXPR_CXX26 S& operator =( S&& rhs) { i_ = rhs.i_ ; rhs.i_ = -2 ; assert (this != &rhs); return *this ; }
34
+ TEST_CONSTEXPR_CXX26 S& operator =(int i) { i_ = i; return *this ; }
37
35
38
- bool operator <(const S& rhs) const { return i_ < rhs.i_ ; }
39
- bool operator ==(const S& rhs) const { return i_ == rhs.i_ ; }
40
- bool operator ==(int i) const { return i_ == i; }
36
+ TEST_CONSTEXPR_CXX26 bool operator <(const S& rhs) const { return i_ < rhs.i_ ; }
37
+ TEST_CONSTEXPR_CXX26 bool operator ==(const S& rhs) const { return i_ == rhs.i_ ; }
38
+ TEST_CONSTEXPR_CXX26 bool operator ==(int i) const { return i_ == i; }
41
39
42
- void set (int i) { i_ = i; }
40
+ TEST_CONSTEXPR_CXX26 void set (int i) { i_ = i; }
43
41
44
42
int i_;
45
43
};
@@ -49,10 +47,9 @@ std::mt19937 randomness;
49
47
50
48
template <class Iter >
51
49
void
52
- test_one (unsigned N, unsigned M)
50
+ test_one_randomized (unsigned N, unsigned M)
53
51
{
54
52
typedef typename std::iterator_traits<Iter>::value_type value_type;
55
- assert (M <= N);
56
53
value_type* ia = new value_type[N];
57
54
for (unsigned i = 0 ; i < N; ++i)
58
55
ia[i] = i;
@@ -70,7 +67,36 @@ test_one(unsigned N, unsigned M)
70
67
}
71
68
72
69
template <class Iter >
73
- void
70
+ TEST_CONSTEXPR_CXX26 void test_one_non_randomized (unsigned N, unsigned M) {
71
+ typedef typename std::iterator_traits<Iter>::value_type value_type;
72
+ value_type* ia = new value_type[N];
73
+ const unsigned long small_prime = 19937 ;
74
+ const unsigned long large_prime = 212987 ;
75
+ unsigned long product_mod = small_prime;
76
+ for (unsigned i = 0 ; i < N; ++i) {
77
+ ia[i] = static_cast <int >(product_mod);
78
+ product_mod = product_mod * small_prime % large_prime;
79
+ }
80
+ std::sort (ia, ia + M);
81
+ std::sort (ia + M, ia + N);
82
+ std::inplace_merge (Iter (ia), Iter (ia + M), Iter (ia + N));
83
+ if (N > 0 ) {
84
+ assert (std::is_sorted (ia, ia + N));
85
+ }
86
+ delete[] ia;
87
+ }
88
+
89
+ template <class Iter >
90
+ TEST_CONSTEXPR_CXX26 void test_one (unsigned N, unsigned M) {
91
+ assert (M <= N);
92
+ if (!TEST_IS_CONSTANT_EVALUATED) {
93
+ test_one_randomized<Iter>(N, M);
94
+ }
95
+ test_one_non_randomized<Iter>(N, M);
96
+ }
97
+
98
+ template <class Iter >
99
+ TEST_CONSTEXPR_CXX26 void
74
100
test (unsigned N)
75
101
{
76
102
test_one<Iter>(N, 0 );
@@ -81,7 +107,7 @@ test(unsigned N)
81
107
}
82
108
83
109
template <class Iter >
84
- void
110
+ TEST_CONSTEXPR_CXX26 void
85
111
test ()
86
112
{
87
113
test_one<Iter>(0 , 0 );
@@ -95,11 +121,19 @@ test()
95
121
test_one<Iter>(3 , 2 );
96
122
test_one<Iter>(3 , 3 );
97
123
test<Iter>(4 );
98
- test<Iter>(100 );
99
- test<Iter>(1000 );
124
+ #if defined(_LIBCPP_HARDENING_MODE)
125
+ if (!TEST_IS_CONSTANT_EVALUATED) // avoid blowing past constant evaluation limit
126
+ #endif
127
+ {
128
+ test<Iter>(100 );
129
+ }
130
+ if (!TEST_IS_CONSTANT_EVALUATED) { // avoid blowing past constant evaluation limit
131
+ test<Iter>(1000 );
132
+ }
100
133
}
101
134
102
- int main (int , char **)
135
+ TEST_CONSTEXPR_CXX26 bool
136
+ test ()
103
137
{
104
138
test<bidirectional_iterator<int *> >();
105
139
test<random_access_iterator<int *> >();
@@ -111,8 +145,17 @@ int main(int, char**)
111
145
test<S*>();
112
146
#endif
113
147
148
+ return true ;
149
+ }
150
+
151
+ int main (int , char **) {
152
+ test ();
153
+ #if TEST_STD_VER >= 26
154
+ static_assert (test ());
155
+ #endif // TEST_STD_VER >= 26
156
+
114
157
#if TEST_STD_VER >= 11 && !defined(TEST_HAS_NO_EXCEPTIONS)
115
- {
158
+ if (!TEST_IS_CONSTANT_EVALUATED) {
116
159
std::vector<int > vec (150 , 3 );
117
160
getGlobalMemCounter ()->throw_after = 0 ;
118
161
std::inplace_merge (vec.begin (), vec.begin () + 100 , vec.end ());
0 commit comments