CodeNebula
C++20stladvanced

std::ranges::mismatch / equal (C++20 Addition)

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

Explanation

`mismatch` finds the first position where two ranges differ, returning a pair of iterators. `equal` checks if two ranges are element-wise equal. Both support projections.

Real-World Scenario

Compare two firmware versions byte-by-byte to find the first differing offset during a delta update.

Quick Snippet

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

std::vector<int> v1 = {1, 2, 3, 4};
std::vector<int> v2 = {1, 2, 5, 4};

auto [it1, it2] = std::ranges::mismatch(v1, v2);
// *it1 == 3, *it2 == 5

bool same = std::ranges::equal(v1, v2);  // false

Full Example

ranges_mismatch_equal.cpp
// CodeNebula - C++20 Example: ranges::mismatch, equal
// Compile: g++ -std=c++20 -Wall -Wextra -o example ranges_mismatch_equal.cpp

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

int main() {
    std::vector<int> a = {1, 2, 3, 4, 5};
    std::vector<int> b = {1, 2, 3, 4, 5};
    std::vector<int> c = {1, 2, 9, 4, 5};

    std::cout << std::boolalpha;
    std::cout << "a == b: " << std::ranges::equal(a, b) << "\n";
    std::cout << "a == c: " << std::ranges::equal(a, c) << "\n";

    // Equal with custom comparator (absolute value)
    std::vector<int> d = {-1, -2, -3, -4, -5};
    std::cout << "a abs-equal d: " << std::ranges::equal(a, d,
        [](int x, int y) { return std::abs(x) == std::abs(y); }) << "\n";

    // Equal with projection (case-insensitive strings)
    std::vector<std::string> words1 = {"Hello", "WORLD"};
    std::vector<std::string> words2 = {"hello", "world"};
    auto to_lower = [](const std::string& s) {
        std::string low = s;
        for (char& ch : low) ch = static_cast<char>(std::tolower(ch));
        return low;
    };
    std::cout << "Case-insensitive equal: "
              << std::ranges::equal(words1, words2, {}, to_lower, to_lower) << "\n";

    // ranges::mismatch - find first differing position
    auto [it1, it2] = std::ranges::mismatch(a, c);
    if (it1 != a.end())
        std::cout << "\nMismatch at index " << (it1 - a.begin())
                  << ": " << *it1 << " vs " << *it2 << "\n";

    // Mismatch when ranges are equal
    auto [m1, m2] = std::ranges::mismatch(a, b);
    std::cout << "a vs b mismatch at end: " << (m1 == a.end()) << "\n";

    // Mismatch with different-length ranges (prefix check)
    std::vector<int> shorter = {1, 2, 3};
    auto [s1, s2] = std::ranges::mismatch(a, shorter);
    if (s2 == shorter.end())
        std::cout << "Shorter is prefix of a (" << shorter.size() << " elements)\n";

    // Mismatch with strings
    std::string str1 = "abcdefgh", str2 = "abcXefgh";
    auto [c1, c2] = std::ranges::mismatch(str1, str2);
    if (c1 != str1.end())
        std::cout << "\nString mismatch at index " << (c1 - str1.begin())
                  << ": '" << *c1 << "' vs '" << *c2 << "'\n";

    // Equal on views
    std::cout << "\niota(1,6) == a: "
              << std::ranges::equal(std::views::iota(1, 6), a) << "\n";

    // Mismatch with predicate (x == 2*y)
    std::vector<int> e = {2, 4, 6, 8, 10};
    std::vector<int> f = {1, 2, 3, 5, 5};
    auto [p1, p2] = std::ranges::mismatch(e, f,
        [](int x, int y) { return x == y * 2; });
    if (p1 != e.end())
        std::cout << "Double mismatch at index " << (p1 - e.begin())
                  << ": " << *p1 << " != 2*" << *p2 << "\n";
    return 0;
}
Run command
g++ -std=c++20 -Wall -Wextra -o example ranges_mismatch_equal.cpp