C++ Algorithm: std::adjacent_find

The std::adjacent_find function in C++ is part of the <algorithm> header and is used to identify the first occurrence of two consecutive identical elements in a range. It returns an iterator to the first element of this pair. If no such pair is found, it returns the end iterator.


Syntax of std::adjacent_find

</>
Copy
template <class ForwardIterator>
ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last);

template <class ForwardIterator, class BinaryPredicate>
ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last,
                              BinaryPredicate pred);

Parameters of std::adjacent_find

ParameterDescription
first, lastForward iterators defining the range to be examined. The range used is [first, last), which includes all elements between first and last, excluding the element pointed to by last.
pred(Optional) A binary function that takes two elements as arguments and returns a boolean value. It defines the condition to be satisfied for two consecutive elements to be considered a match. The function should not modify its arguments.

Return Value of std::adjacent_find

An iterator to the first element of the first pair of matching consecutive elements in the specified range. If no such pair is found, the function returns last.


Example: Using std::adjacent_find to Find Consecutive Duplicate Elements

In this example, we use std::adjacent_find to locate the first occurrence of consecutive duplicate elements in a vector.

Program

</>
Copy
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numbers = {1, 2, 3, 3, 4, 5};

    auto it = std::adjacent_find(numbers.begin(), numbers.end());

    if (it != numbers.end()) {
        std::cout << "First pair of adjacent duplicates found at position "
                  << std::distance(numbers.begin(), it)
                  << " with value " << *it << ".\n";
    } else {
        std::cout << "No adjacent duplicates found.\n";
    }

    return 0;
}

Output

First pair of adjacent duplicates found at position 2 with value 3.

Explanation

  1. We include the necessary headers: <iostream> for input/output operations, <vector> for the std::vector container, and <algorithm> for the std::adjacent_find function.
  2. We define a vector numbers containing the integers {1, 2, 3, 3, 4, 5}.
  3. We use std::adjacent_find to search for the first occurrence of consecutive duplicate elements in numbers.
  4. If such a pair is found, it points to the first element of the pair, and we print its position and value. Otherwise, we print that no adjacent duplicates were found.

Example: Using std::adjacent_find with a Custom Comparator

This example demonstrates how to use std::adjacent_find with a custom comparator to find the first occurrence of two consecutive elements that satisfy a specific condition.

Program

</>
Copy
#include <iostream>
#include <vector>
#include <algorithm>

bool difference_of_one(int a, int b) {
    return std::abs(a - b) == 1;
}

int main() {
    std::vector<int> numbers = {1, 2, 4, 5, 7, 8};

    auto it = std::adjacent_find(numbers.begin(), numbers.end(), difference_of_one);

    if (it != numbers.end()) {
        std::cout << "First pair of adjacent elements with a difference of one found at position "
                  << std::distance(numbers.begin(), it)
                  << " with values " << *it << " and " << *(it + 1) << ".\n";
    } else {
        std::cout << "No adjacent elements with a difference of one found.\n";
    }

    return 0;
}

Output

First pair of adjacent elements with a difference of one found at position 0 with values 1 and 2.

Explanation

  1. We include the necessary headers: <iostream> for input/output operations, <vector> for the std::vector container, and <algorithm> for the std::adjacent_find function.
  2. We define a custom comparator function difference_of_one that returns true if the absolute difference between two integers is 1.
  3. We define a vector numbers containing the integers {1, 2, 4, 5, 7, 8}.
  4. We use std::adjacent_find with the custom comparator to search for the first pair of adjacent elements in numbers that have a difference of one.
  5. If such a pair is found, it points to the first element of the pair, and we print its position and the values of both elements. Otherwise, we print that no such adjacent elements were found.

Examples for Exceptions Thrown by std::adjacent_find

The std::adjacent_find function can throw exceptions in the following cases:

  • If the comparison operation or predicate (pred) throws an exception.
  • If an operation on the iterators, such as dereferencing or incrementing, throws an exception.

Example 1: Predicate Throws an Exception

This example demonstrates a case where the predicate function throws an exception during execution.

Program

</>
Copy
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>

bool faulty_predicate(int a, int b) {
    if (a < 0 || b < 0) {
        throw std::runtime_error("Negative value encountered during comparison.");
    }
    return a == b;
}

int main() {
    std::vector<int> numbers = {1, -2, -2, 4, 5};

    try {
        auto it = std::adjacent_find(numbers.begin(), numbers.end(), faulty_predicate);

        if (it != numbers.end()) {
            std::cout << "First adjacent pair found with value: " << *it << '\n';
        } else {
            std::cout << "No adjacent pair found.\n";
        }
    } catch (const std::runtime_error& e) {
        std::cout << "Exception caught: " << e.what() << '\n';
    }

    return 0;
}

Output

Exception caught: Negative value encountered during comparison.

Explanation

  1. The program defines a predicate function faulty_predicate that throws a std::runtime_error if either value being compared is negative.
  2. The vector numbers contains integers, including negative values.
  3. The std::adjacent_find function applies the predicate to each pair of consecutive elements in numbers. When the predicate encounters negative values, it throws an exception.
  4. The exception is caught in the try-catch block, and an error message is printed.

Example 2: Iterator Throws an Exception

This example demonstrates a case where a custom iterator throws an exception during iteration.

Program

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>

class FaultyIterator {
public:
    using iterator_category = std::forward_iterator_tag;
    using value_type = int;
    using difference_type = std::ptrdiff_t;
    using pointer = const int*;
    using reference = const int&;

    FaultyIterator(const int* ptr, bool fail_after = false)
        : ptr(ptr), fail_after(fail_after), count(0) {}

    reference operator*() const {
        if (fail_after && count >= 2) {
            throw std::runtime_error("Iterator error during dereference.");
        }
        return *ptr;
    }

    FaultyIterator& operator++() {
        ++ptr;
        ++count;
        return *this;
    }

    bool operator!=(const FaultyIterator& other) const {
        return ptr != other.ptr;
    }

    bool operator==(const FaultyIterator& other) const {
        return ptr == other.ptr;
    }

private:
    const int* ptr;
    bool fail_after;
    int count;
};

int main() {
    int arr[] = {1, 2, 2, 3, 4};

    try {
        auto it = std::adjacent_find(
            FaultyIterator(arr, true),
            FaultyIterator(arr + 5)
        );

        if (it != FaultyIterator(arr + 5)) {
            std::cout << "First adjacent pair found with value: " << *it << '\n';
        } else {
            std::cout << "No adjacent pair found.\n";
        }
    } catch (const std::runtime_error& e) {
        std::cout << "Exception caught: " << e.what() << '\n';
    }

    return 0;
}

Output

Exception caught: Iterator error during dereference.

Explanation

  1. The program defines a custom iterator FaultyIterator that throws a std::runtime_error after accessing two elements.
  2. An array arr contains five elements.
  3. The std::adjacent_find function uses the custom iterator to search for the first adjacent pair of elements in the array.
  4. The iterator throws an exception during the third access, which is caught in the try-catch block, and an error message is printed.