diff --git a/tests/std/tests/VSO_0000000_vector_algorithms_search_n/test.cpp b/tests/std/tests/VSO_0000000_vector_algorithms_search_n/test.cpp index 04b3907b83c..08b825855f2 100644 --- a/tests/std/tests/VSO_0000000_vector_algorithms_search_n/test.cpp +++ b/tests/std/tests/VSO_0000000_vector_algorithms_search_n/test.cpp @@ -12,8 +12,49 @@ #include "test_vector_algorithms_support.hpp" +#pragma warning(disable : 4984) // if constexpr is a C++17 language extension +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wc++17-extensions" +#endif // __clang__ + using namespace std; +template +struct forward_iter_adaptor { + using iterator_category = forward_iterator_tag; + using reference = typename UnderlyingIt::reference; + using value_type = typename UnderlyingIt::value_type; + using pointer = typename UnderlyingIt::pointer; + using difference_type = ptrdiff_t; + + constexpr forward_iter_adaptor() : ptr{} {} + constexpr explicit forward_iter_adaptor(const UnderlyingIt ptr_) : ptr(ptr_) {} + + constexpr reference operator*() const { + return *ptr; + } + constexpr pointer operator->() const { + return ptr; + } + constexpr forward_iter_adaptor& operator++() { + ++ptr; + return *this; + } + constexpr forward_iter_adaptor operator++(int) { + forward_iter_adaptor old; + ++ptr; + return old; + } + constexpr bool operator==(const forward_iter_adaptor& o) const { + return ptr == o.ptr; + } + constexpr bool operator!=(const forward_iter_adaptor& o) const { + return ptr != o.ptr; + } + + UnderlyingIt ptr; +}; + template auto last_known_good_search_n(FwdIt first, const FwdIt last, const size_t count, const T val) { // 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, return last; } -template -void test_case_search_n(const Container& c, size_t count, T val) { - auto expected = last_known_good_search_n(c.begin(), c.end(), count, val); - auto actual = search_n(c.begin(), c.end(), count, val); - assert(expected == actual); +template +void test_case_search_n(const It first, const It last, const size_t count, const T val) { + if constexpr (forward_only_iterators) { + using iter_type = forward_iter_adaptor; + test_case_search_n(iter_type(first), iter_type(last), count, val); + } else { + const auto expected = last_known_good_search_n(first, last, count, val); + const auto actual = search_n(first, last, count, val); + assert(expected == actual); #if _HAS_CXX20 - auto ranges_actual = ranges::search_n(c, static_cast(count), val); - assert(expected == begin(ranges_actual)); - if (expected == c.end()) { - assert(end(ranges_actual) == c.end()); - } else { - assert(distance(expected, end(ranges_actual)) == static_cast(count)); - } + const auto ranges_actual = ranges::search_n(first, last, static_cast(count), val); + assert(expected == begin(ranges_actual)); + if (expected == last) { + assert(end(ranges_actual) == last); + } else { + assert(distance(expected, end(ranges_actual)) == static_cast(count)); + } #endif // _HAS_CXX20 + } } -template +template void test_search_n(mt19937_64& gen) { constexpr size_t lengthCount = 70; constexpr size_t patternCount = 5; @@ -74,7 +120,7 @@ void test_search_n(mt19937_64& gen) { const T val = static_cast(dis(gen)); - test_case_search_n(input, count, val); + test_case_search_n(input.begin(), input.end(), count, val); if (input.empty()) { continue; @@ -90,7 +136,7 @@ void test_search_n(mt19937_64& gen) { if (pattern_length + pattern_pos <= input.size()) { fill_n(input.begin() + static_cast(pattern_pos), pattern_length, val); - test_case_search_n(input, count, val); + test_case_search_n(input.begin(), input.end(), count, val); } } } @@ -113,6 +159,10 @@ void test_vector_algorithms(mt19937_64& gen) { test_search_n(gen); test_search_n(gen); test_search_n(gen); + + // Test only one case with forward iterators. It is a different and complex code path, hence it's worth testing, + // but it is not vectorized, so there's no point in trying different types. + test_search_n(gen); } int main() {