12
12
13
13
#include " test_vector_algorithms_support.hpp"
14
14
15
+ #pragma warning(disable : 4984) // if constexpr is a C++17 language extension
16
+ #ifdef __clang__
17
+ #pragma clang diagnostic ignored "-Wc++17-extensions"
18
+ #endif // __clang__
19
+
15
20
using namespace std ;
16
21
22
+ template <class UnderlyingIt >
23
+ struct forward_iter_adaptor {
24
+ using iterator_category = forward_iterator_tag;
25
+ using reference = typename UnderlyingIt::reference;
26
+ using value_type = typename UnderlyingIt::value_type;
27
+ using pointer = typename UnderlyingIt::pointer;
28
+ using difference_type = ptrdiff_t ;
29
+
30
+ constexpr forward_iter_adaptor () : ptr{} {}
31
+ constexpr explicit forward_iter_adaptor (const UnderlyingIt ptr_) : ptr(ptr_) {}
32
+
33
+ constexpr reference operator *() const {
34
+ return *ptr;
35
+ }
36
+ constexpr pointer operator ->() const {
37
+ return ptr;
38
+ }
39
+ constexpr forward_iter_adaptor& operator ++() {
40
+ ++ptr;
41
+ return *this ;
42
+ }
43
+ constexpr forward_iter_adaptor operator ++(int ) {
44
+ forward_iter_adaptor old;
45
+ ++ptr;
46
+ return old;
47
+ }
48
+ constexpr bool operator ==(const forward_iter_adaptor& o) const {
49
+ return ptr == o.ptr ;
50
+ }
51
+ constexpr bool operator !=(const forward_iter_adaptor& o) const {
52
+ return ptr != o.ptr ;
53
+ }
54
+
55
+ UnderlyingIt ptr;
56
+ };
57
+
17
58
template <class FwdIt , class T >
18
59
auto last_known_good_search_n (FwdIt first, const FwdIt last, const size_t count, const T val) {
19
60
// Deliberately using simple approach, not smart bidi/random iterators "check from the other end" stuff
@@ -40,24 +81,29 @@ auto last_known_good_search_n(FwdIt first, const FwdIt last, const size_t count,
40
81
return last;
41
82
}
42
83
43
- template <class Container , class T >
44
- void test_case_search_n (const Container& c, size_t count, T val) {
45
- auto expected = last_known_good_search_n (c.begin (), c.end (), count, val);
46
- auto actual = search_n (c.begin (), c.end (), count, val);
47
- assert (expected == actual);
84
+ template <bool forward_only_iterators, class It , class T >
85
+ void test_case_search_n (const It first, const It last, const size_t count, const T val) {
86
+ if constexpr (forward_only_iterators) {
87
+ using iter_type = forward_iter_adaptor<It>;
88
+ test_case_search_n<false >(iter_type (first), iter_type (last), count, val);
89
+ } else {
90
+ const auto expected = last_known_good_search_n (first, last, count, val);
91
+ const auto actual = search_n (first, last, count, val);
92
+ assert (expected == actual);
48
93
49
94
#if _HAS_CXX20
50
- auto ranges_actual = ranges::search_n (c , static_cast <ptrdiff_t >(count), val);
51
- assert (expected == begin (ranges_actual));
52
- if (expected == c. end () ) {
53
- assert (end (ranges_actual) == c. end () );
54
- } else {
55
- assert (distance (expected, end (ranges_actual)) == static_cast <ptrdiff_t >(count));
56
- }
95
+ const auto ranges_actual = ranges::search_n (first, last , static_cast <ptrdiff_t >(count), val);
96
+ assert (expected == begin (ranges_actual));
97
+ if (expected == last ) {
98
+ assert (end (ranges_actual) == last );
99
+ } else {
100
+ assert (distance (expected, end (ranges_actual)) == static_cast <ptrdiff_t >(count));
101
+ }
57
102
#endif // _HAS_CXX20
103
+ }
58
104
}
59
105
60
- template <class T >
106
+ template <class T , bool forward_only_iterators = false >
61
107
void test_search_n (mt19937_64& gen) {
62
108
constexpr size_t lengthCount = 70 ;
63
109
constexpr size_t patternCount = 5 ;
@@ -74,7 +120,7 @@ void test_search_n(mt19937_64& gen) {
74
120
75
121
const T val = static_cast <T>(dis (gen));
76
122
77
- test_case_search_n (input, count, val);
123
+ test_case_search_n<forward_only_iterators> (input. begin (), input. end () , count, val);
78
124
79
125
if (input.empty ()) {
80
126
continue ;
@@ -90,7 +136,7 @@ void test_search_n(mt19937_64& gen) {
90
136
if (pattern_length + pattern_pos <= input.size ()) {
91
137
fill_n (input.begin () + static_cast <ptrdiff_t >(pattern_pos), pattern_length, val);
92
138
93
- test_case_search_n (input, count, val);
139
+ test_case_search_n<forward_only_iterators> (input. begin (), input. end () , count, val);
94
140
}
95
141
}
96
142
}
@@ -113,6 +159,10 @@ void test_vector_algorithms(mt19937_64& gen) {
113
159
test_search_n<unsigned int >(gen);
114
160
test_search_n<long long >(gen);
115
161
test_search_n<unsigned long long >(gen);
162
+
163
+ // Test only one case with forward iterators. It is a different and complex code path, hence it's worth testing,
164
+ // but it is not vectorized, so there's no point in trying different types.
165
+ test_search_n<short , true >(gen);
116
166
}
117
167
118
168
int main () {
0 commit comments