Skip to content

Commit 36f37d6

Browse files
1 parent e90e199 commit 36f37d6

File tree

1 file changed

+65
-15
lines changed
  • tests/std/tests/VSO_0000000_vector_algorithms_search_n

1 file changed

+65
-15
lines changed

tests/std/tests/VSO_0000000_vector_algorithms_search_n/test.cpp

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,49 @@
1212

1313
#include "test_vector_algorithms_support.hpp"
1414

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+
1520
using namespace std;
1621

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+
1758
template <class FwdIt, class T>
1859
auto last_known_good_search_n(FwdIt first, const FwdIt last, const size_t count, const T val) {
1960
// 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,
4081
return last;
4182
}
4283

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);
4893

4994
#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+
}
57102
#endif // _HAS_CXX20
103+
}
58104
}
59105

60-
template <class T>
106+
template <class T, bool forward_only_iterators = false>
61107
void test_search_n(mt19937_64& gen) {
62108
constexpr size_t lengthCount = 70;
63109
constexpr size_t patternCount = 5;
@@ -74,7 +120,7 @@ void test_search_n(mt19937_64& gen) {
74120

75121
const T val = static_cast<T>(dis(gen));
76122

77-
test_case_search_n(input, count, val);
123+
test_case_search_n<forward_only_iterators>(input.begin(), input.end(), count, val);
78124

79125
if (input.empty()) {
80126
continue;
@@ -90,7 +136,7 @@ void test_search_n(mt19937_64& gen) {
90136
if (pattern_length + pattern_pos <= input.size()) {
91137
fill_n(input.begin() + static_cast<ptrdiff_t>(pattern_pos), pattern_length, val);
92138

93-
test_case_search_n(input, count, val);
139+
test_case_search_n<forward_only_iterators>(input.begin(), input.end(), count, val);
94140
}
95141
}
96142
}
@@ -113,6 +159,10 @@ void test_vector_algorithms(mt19937_64& gen) {
113159
test_search_n<unsigned int>(gen);
114160
test_search_n<long long>(gen);
115161
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);
116166
}
117167

118168
int main() {

0 commit comments

Comments
 (0)