CodeNebula
C++20stladvanced

std::ranges::search / search_n (C++20 Addition)

C++20 · The Big Four · Compiler flag: -std=c++20

Explanation

`search` finds the first occurrence of a subsequence within a range. `search_n` finds the first run of N consecutive matching elements.

Real-World Scenario

Locate a specific byte pattern in a binary protocol stream.

Quick Snippet

snippet.cpp
#include <ranges>
#include <algorithm>
#include <vector>

std::vector<int> data = {1, 2, 3, 4, 2, 3};
std::vector<int> pattern = {2, 3};

auto [first, last] = std::ranges::search(data, pattern);
auto run = std::ranges::search_n(data, 1, 2);  // first occurrence of one '2'

Full Example

ranges_search.cpp
// CodeNebula - C++20 Example: ranges::search, search_n
// Compile: g++ -std=c++20 -Wall -Wextra -o example ranges_search.cpp

#include <iostream>
#include <ranges>
#include <vector>
#include <string>
#include <algorithm>

int main() {
    // ranges::search - find first occurrence of a subsequence
    std::vector<int> data = {1, 2, 3, 4, 5, 1, 2, 3, 6, 7};
    std::vector<int> pattern = {1, 2, 3};

    auto [first, last] = std::ranges::search(data, pattern);
    if (first != data.end())
        std::cout << "Pattern {1,2,3} found at index "
                  << (first - data.begin()) << "\n";

    // Search for missing pattern
    std::vector<int> missing = {8, 9};
    auto [f2, l2] = std::ranges::search(data, missing);
    std::cout << "Pattern {8,9} found: " << std::boolalpha
              << (f2 != data.end()) << "\n";

    // Search in strings
    std::string text = "the quick brown fox jumps over the lazy dog";
    auto [sf, sl] = std::ranges::search(text, std::string("fox"));
    if (sf != text.end())
        std::cout << "\n\"fox\" found at index " << (sf - text.begin()) << "\n";

    // Case-insensitive search
    std::string haystack = "Hello World HELLO World";
    auto [ci_f, ci_l] = std::ranges::search(haystack, std::string("hello"),
        [](char a, char b) { return std::tolower(a) == std::tolower(b); });
    if (ci_f != haystack.end())
        std::cout << "Case-insensitive \"hello\" at index "
                  << (ci_f - haystack.begin()) << "\n";

    // ranges::search_n - find N consecutive occurrences of a value
    std::vector<int> seq = {1, 2, 2, 2, 3, 4, 4, 5, 5, 5, 5};

    auto [sn_f, sn_l] = std::ranges::search_n(seq, 3, 2);
    if (sn_f != seq.end())
        std::cout << "\n3 consecutive 2s at index " << (sn_f - seq.begin()) << "\n";

    auto [sn_f2, sn_l2] = std::ranges::search_n(seq, 4, 5);
    if (sn_f2 != seq.end())
        std::cout << "4 consecutive 5s at index " << (sn_f2 - seq.begin()) << "\n";

    // search_n not found
    auto [sn_f3, sn_l3] = std::ranges::search_n(seq, 5, 5);
    std::cout << "5 consecutive 5s found: " << (sn_f3 != seq.end()) << "\n";

    // search_n with predicate (consecutive even numbers)
    std::vector<int> nums = {1, 4, 6, 8, 3, 2, 4, 7};
    auto [ep_f, ep_l] = std::ranges::search_n(nums, 3, 0,
        [](int a, [[maybe_unused]] int b) { return a % 2 == 0; });
    if (ep_f != nums.end())
        std::cout << "\n3 consecutive evens at index "
                  << (ep_f - nums.begin()) << "\n";

    // search_n with projection
    std::vector<std::string> words = {"cat", "car", "cup", "dog", "dot"};
    auto [wp_f, wp_l] = std::ranges::search_n(words, 2, 'd', std::equal_to{},
        [](const std::string& s) { return s.front(); });
    if (wp_f != words.end())
        std::cout << "2 'd'-words at index " << (wp_f - words.begin()) << "\n";
    return 0;
}
Run command
g++ -std=c++20 -Wall -Wextra -o example ranges_search.cpp