C++ <algorithm> std::equal

The std::equal function template in C++ is used to determine if two sequences are equal by comparing their elements pairwise. It is included in the <algorithm> header and provides a convenient way to compare ranges of elements.


Syntax of std::equal

</>
Copy

template <class InputIterator1, class InputIterator2>
bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2);

template <class InputIterator1, class InputIterator2, class BinaryPredicate>
bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate pred);

Parameters of std::equal

ParameterDescription
first1, last1Input iterators defining the range [first1, last1) for the first sequence.
first2Input iterator to the beginning of the second sequence. The function compares elements in the range starting from first2 up to the distance [first1, last1).
pred (optional)Binary predicate that takes two elements as arguments (one from each sequence) and returns a boolean indicating whether they are considered equal. If not provided, the function uses operator== by default.

Return Value of std::equal

The function returns a boolean value:

  • true if all the elements in the range [first1, last1) compare equal to those of the range starting at first2.
  • false otherwise.

Examples for algorithm equal function

Example 1: Comparing Two Arrays for Equality

In this example, we use std::equal to check if two arrays of integers are equal.

Program

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

int main() {
    int array1[] = {1, 2, 3, 4, 5};
    int array2[] = {1, 2, 3, 4, 5};

    bool are_equal = std::equal(std::begin(array1), std::end(array1), std::begin(array2));

    if (are_equal) {
        std::cout << "The arrays are equal." << std::endl;
    } else {
        std::cout << "The arrays are not equal." << std::endl;
    }

    return 0;
}

Output

The arrays are equal.

Explanation

  1. We include the necessary headers: <iostream> for input/output operations and <algorithm> for the std::equal function.
  2. We define two arrays, array1 and array2, each containing five integers with identical values.
  3. We call std::equal, passing iterators to the beginning and end of array1, and the beginning of array2. The function compares corresponding elements from both arrays.
  4. The function returns true since all corresponding elements are equal.
  5. We print a message indicating that the arrays are equal.

Example 2: Comparing Two Vectors with a Custom Predicate

In this example, we use std::equal with a custom predicate to compare two vectors of integers, considering elements equal if their absolute values are the same.

Program

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

bool abs_equal(int a, int b) {
    return std::abs(a) == std::abs(b);
}

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

    bool are_equal = std::equal(vec1.begin(), vec1.end(), vec2.begin(), abs_equal);

    if (are_equal) {
        std::cout << "The vectors are equal based on absolute values." << std::endl;
    } else {
        std::cout << "The vectors are not equal based on absolute values." << std::endl;
    }

    return 0;
}

Output

The vectors are equal based on absolute values.

Explanation

  1. We include the necessary headers: <iostream> for input/output operations, <vector> for the std::vector container, <algorithm> for the std::equal function, and <cmath> for the std::abs function.
  2. We define a custom predicate function abs_equal that returns true if the absolute values of two integers are equal.
  3. We create two vectors, vec1 and vec2, containing integers with corresponding elements having the same absolute values.
  4. We call std::equal, passing iterators to the beginning and end of vec1, the beginning of vec2, and the custom predicate abs_equal. The function compares corresponding elements using the custom predicate.
  5. The function returns true since all corresponding elements are equal based on their absolute values.
  6. We print a message indicating that the vectors are equal based on absolute values.

Example 3: Checking for Palindrome Using std::equal

In this example, we use std::equal to check if a string is a palindrome by comparing its characters with their counterparts in reverse order.

Program

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

int main() {
    std::string str = "radar";

    bool is_palindrome = std::equal(str.begin(), str.begin() + str.size() / 2, str.rbegin());

    if (is_palindrome) {
        std::cout << "The string \"" << str << "\" is a palindrome." << std::endl;
    } else {
        std::cout << "The string \"" << str << "\" is not a palindrome." << std::endl;
    }

    return 0;
}

Output

The string "radar" is a palindrome.

Explanation

  1. We include the necessary headers: <iostream> for input/output operations, <string> for the std::string class, and <algorithm> for the std::equal function.
  2. We define a string str initialized with the value “radar”.
  3. We call std::equal to compare the first half of the string with its reverse counterpart. This is achieved by iterating from the beginning of the string to the middle (str.begin() + str.size() / 2) and comparing it with the reverse iterator str.rbegin().
  4. If all corresponding characters match, std::equal returns true, indicating that the string is a palindrome.
  5. The result is stored in is_palindrome, which is then used to print an appropriate message indicating whether the string is a palindrome.

Examples for Exceptions Thrown by std::equal

The std::equal function can throw exceptions in the following scenarios:

  • If the element comparison or the 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> vec1 = {1, -2, 3, 4};
    std::vector<int> vec2 = {1, 2, 3, 4};

    try {
        bool are_equal = std::equal(vec1.begin(), vec1.end(), vec2.begin(), faulty_predicate);
        if (are_equal) {
            std::cout << "The vectors are equal." << std::endl;
        } else {
            std::cout << "The vectors are not equal." << std::endl;
        }
    } catch (const std::runtime_error& e) {
        std::cout << "Exception caught: " << e.what() << std::endl;
    }

    return 0;
}

Output

Exception caught: Negative value encountered during comparison.

Explanation

  1. We define a custom predicate faulty_predicate that throws a std::runtime_error if either input value is negative.
  2. We initialize two vectors, vec1 and vec2, where vec1 contains a negative value.
  3. The std::equal function applies the predicate to corresponding elements from both vectors. When the predicate encounters a negative value, 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

</>
Copy
#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;
    }

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

int main() {
    int arr1[] = {1, 2, 3, 4};
    int arr2[] = {1, 2, 0, 4};

    try {
        bool are_equal = std::equal(
            FaultyIterator(arr1, true),
            FaultyIterator(arr1 + 4),
            FaultyIterator(arr2)
        );

        if (are_equal) {
            std::cout << "The sequences are equal." << std::endl;
        } else {
            std::cout << "The sequences are not equal." << std::endl;
        }
    } catch (const std::runtime_error& e) {
        std::cout << "Exception caught: " << e.what() << std::endl;
    }

    return 0;
}

Output

Exception caught: Iterator error during dereference.

Explanation

  1. We define a custom iterator FaultyIterator that throws a std::runtime_error after accessing two elements.
  2. We create two arrays, arr1 and arr2, for comparison.
  3. The std::equal function uses the custom iterator to compare the elements in both arrays.
  4. The iterator throws an exception during the third access, which is caught in the try-catch block, and an error message is printed.