Namespaces
Variants

std::ranges::equal

From cppreference.com
 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy, ranges::sort, ...
Non-modifying sequence operations    
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17)(C++11)
(C++20)(C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
(C++11)    

Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
(C++11)
(C++17)
Lexicographical comparison operations
Permutation operations


 
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations (on sorted ranges)
       
       
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
       
       
Permutation operations
Fold operations
Numeric operations
(C++23)            
Operations on uninitialized storage
Return types
 
Defined in header <algorithm>
Call signature
template< std::input_iterator I1, std::sentinel_for<I1> S1,
          std::input_iterator I2, std::sentinel_for<I2> S2,
          class Pred = ranges::equal_to,
          class Proj1 = std::identity, class Proj2 = std::identity >
    requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
constexpr bool equal( I1 first1, S1 last1, I2 first2, S2 last2,
                      Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );
(1) (since C++20)
template< ranges::input_range R1, ranges::input_range R2,
          class Pred = ranges::equal_to,
          class Proj1 = std::identity, class Proj2 = std::identity >
    requires std::indirectly_comparable
                 <ranges::iterator_t<R1>, ranges::iterator_t<R2>,
                  Pred, Proj1, Proj2>
constexpr bool equal( R1&& r1, R2&& r2,
                      Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );
(2) (since C++20)
template< /*execution-policy*/ Ep,
          std::random_access_iterator I1, std::sized_sentinel_for<I1> S1,
          std::random_access_iterator I2, std::sized_sentinel_for<I2> S2,
          class Pred = ranges::equal_to,
          class Proj1 = std::identity, class Proj2 = std::identity >
    requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
bool equal( Ep&& policy, I1 first1, S1 last1, I2 first2, S2 last2,
            Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );
(3) (since C++26)
template< /*execution-policy*/ Ep, /*sized-random-access-range*/ R1,
          /*sized-random-access-range*/ R2,
          class Pred = ranges::equal_to,
          class Proj1 = std::identity, class Proj2 = std::identity >
    requires std::indirectly_comparable
                 <ranges::iterator_t<R1>, ranges::iterator_t<R2>,
                  Pred, Proj1, Proj2>
bool equal( Ep&& policy, R1&& r1, R2&& r2,
            Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {} );
(4) (since C++26)

For the definition of /*execution-policy*/, see this page; for the definition of /*sized-random-access-range*/, see this page.

Checks whether two target ranges are equal. The elements (projected by proj1 and proj2 respectively) are compared using the binary predicate pred.

1) The target ranges are [first1last1) and [first2last2).
2) The target ranges are r1 and r2.
3,4) Same as (1,2), but executed according to policy.

The function-like entities described on this page are algorithm function objects (informally known as niebloids), that is:

Parameters

first1, last1 - the iterator-sentinel pair defining the first target range
r1 - the first target range
first2, last2 - the iterator-sentinel pair defining the second target range
r2 - the second target range
pred - the predicate to be applied to the (projected) elements
proj1 - the projection to be applied to the elements in the first target range
proj2 - the projection to be applied to the elements in the second target range

Return value

If the two target ranges have the same size, and each corresponding (projected) elements in the two ranges are equal, returns true. Otherwise returns false.

Complexity

Given

  • N1 as ranges::distance(first1, last1) or ranges::distance(r1), and
  • N2 as ranges::distance(first2, last2) or ranges::distance(r2):
1,2) At most min(N1,N2) applications of pred, proj1 and proj2.
3,4) 𝓞(min(N1,N2)) applications of pred, proj1 and proj2.

If I1, S1, I2 and S2 pairwise model sized_sentinel_for (or both R1 and R2 model sized_range), and N1≠N2, then no comparison will be made.

Exceptions

3,4) During the execution process:
  • If the temporary memory resources required for parallelization are not available, std::bad_alloc is thrown.
  • If an uncaught exception is thrown while accessing objects via an algorithm argument, the behavior is determined by the execution policy (for standard policies, std::terminate is invoked).

Notes

ranges::equal should not be used to compare the ranges formed by the iterators from std::unordered_set, std::unordered_multiset, std::unordered_map, or std::unordered_multimap because the order in which the elements are stored in those containers may be different even if the two containers store the same elements.

When comparing entire containers or string views for equality, operator== for the corresponding type are usually preferred.

ranges::equal is not guaranteed to be short-circuit. E.g. if the first pair elements of both ranges do not compare equal, the rest of elements may also be compared. Non-short-circuit comparison may happen when the ranges are compared with std::memcmp or implementation-specific vectorized algorithms.

Possible implementation

struct equal_fn
{
    template<std::input_iterator I1, std::sentinel_for<I1> S1,
             std::input_iterator I2, std::sentinel_for<I2> S2,
             class Pred = ranges::equal_to,
             class Proj1 = std::identity, class Proj2 = std::identity>
        requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
    constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2,
                              Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const
    {
        if constexpr (std::sized_sentinel_for<S1, I1> && std::sized_sentinel_for<S2, I2>)
            if (ranges::distance(first1, last1) != ranges::distance(first2, last2))
                return false;
        
        for (; first1 != last1; ++first1, (void)++first2)
            if (!std::invoke(pred, std::invoke(proj1, *first1),
                                   std::invoke(proj2, *first2)))
                return false;
        return true;
    }
    
    template<ranges::input_range R>
    constexpr auto get_end(R&& r)
    {
        return ranges::end(r);
    }
    
    template<ranges::forward_range R>
    constexpr auto get_end(R&& r)
    {
        return ranges::next(ranges::begin(r), ranges::end(r));
    }
    
    template<ranges::input_range R1, ranges::input_range R2,
             class Pred = ranges::equal_to,
             class Proj1 = std::identity, class Proj2 = std::identity>
        requires std::indirectly_comparable<ranges::iterator_t<R1>,
                                            ranges::iterator_t<R2>, Pred, Proj1, Proj2>
    constexpr bool operator()(R1&& r1, R2&& r2,
                              Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const
    {
        return (*this)(ranges::begin(r1), get_end(r1),
                       ranges::begin(r2), get_end(r2),
                       std::ref(pred), std::ref(proj1), std::ref(proj2));
    }
};

inline constexpr equal_fn equal;

Example

The following code uses ranges::equal to test if a string is a palindrome.

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <ranges>
#include <string_view>

constexpr bool is_palindrome(const std::string_view s)
{
    namespace views = std::views;
    auto forward = s | views::take(s.size() / 2);
    auto backward = s | views::reverse | views::take(s.size() / 2);
    return std::ranges::equal(forward, backward);
}

void test(const std::string_view s)
{
    std::cout << std::quoted(s) << " is "
              << (is_palindrome(s) ? "" : "not ")
              << "a palindrome\n";
}

int main()
{
    test("radar");
    test("hello");
    static_assert(is_palindrome("ABBA") and not is_palindrome("AC/DC"));
}

Output:

"radar" is a palindrome
"hello" is not a palindrome

See also

determines if two sets of elements are the same
(function template) [edit]
finds the first element satisfying specific criteria
(algorithm function object)[edit]
compares two ranges lexicographically
(algorithm function object)[edit]
finds the first position where two ranges differ
(algorithm function object)[edit]
searches for the first occurrence of a range of elements
(algorithm function object)[edit]
finds the range of elements matching the given value using binary search
(algorithm function object)[edit]
function object implementing x == y
(class template) [edit]
Morty Proxy This is a proxified and sanitized view of the page, visit original site.