Namespaces
Variants

std::equal

Из ru.cppreference.net
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы над диапазонами (C++20)
Ограниченные алгоритмы, например ranges::copy, ranges::sort, ...
Немодифицирующие операции над последовательностями    
Пакетные операции
(C++17)
Операции поиска
Модифицирующие операции над последовательностями
Операции копирования
(C++11)
(C++11)
Операции обмена
Операции преобразования
Операции заполнения
Операции удаления
Операции изменения порядка
(до C++17)(C++11)
(C++20)(C++20)
Операции выборки
(C++17)

Сортировка и связанные операции
Операции разделения
(C++11)    

Операции сортировки
Операции бинарного поиска
(по разделённым диапазонам)
Операции над множествами (на отсортированных диапазонах)
Операции слияния (на отсортированных диапазонах)
Операции над кучей
Операции поиска минимума/максимума
(C++11)
(C++17)
Операции лексикографического сравнения
Операции перестановки


Политики выполнения (C++17)
(только для демонстрации*)(C++26)

Численные операции
(C++11)
(C++17)
(C++17)    

Специализированные <memory> алгоритмы

Специализированные <random> алгоритмы
Библиотека C









 
Определён в заголовочном файле <algorithm>
template< class InputIt1, class InputIt2 >
bool equal( InputIt1 first1, InputIt1 last1,
            InputIt2 first2 );
(1) (constexpr начиная с C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
bool equal( ExecutionPolicy&& policy,
            ForwardIt1 first1, ForwardIt1 last1,
            ForwardIt2 first2 );
(2) (начиная с C++17)
template< class InputIt1, class InputIt2, class BinaryPred >
bool equal( InputIt1 first1, InputIt1 last1,
            InputIt2 first2, BinaryPred p );
(3) (constexpr начиная с C++20)
template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2, class BinaryPred >
bool equal( ExecutionPolicy&& policy,
            ForwardIt1 first1, ForwardIt1 last1,
            ForwardIt2 first2, BinaryPred p );
(4) (начиная с C++17)
template< class InputIt1, class InputIt2 >
bool equal( InputIt1 first1, InputIt1 last1,
            InputIt2 first2, InputIt2 last2 );
(5) (начиная с C++14)
(constexpr начиная с C++20)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
bool equal( ExecutionPolicy&& policy,
            ForwardIt1 first1, ForwardIt1 last1,
            ForwardIt2 first2, ForwardIt2 last2 );
(6) (начиная с C++17)
template< class InputIt1, class InputIt2, class BinaryPred >
bool equal( InputIt1 first1, InputIt1 last1,
            InputIt2 first2, InputIt2 last2, BinaryPred p );
(7) (начиная с C++14)
(constexpr начиная с C++20)
template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2, class BinaryPred >
bool equal( ExecutionPolicy&& policy,
            ForwardIt1 first1, ForwardIt1 last1,
            ForwardIt2 first2, ForwardIt2 last2, BinaryPred p );
(8) (начиная с C++17)

Проверяет, являются ли [first1, last1) и диапазон, начинающийся с first2, равными:

  • Для перегрузок (1-4) второй диапазон содержит std::distance(first1, last1) элементов.
  • Для перегрузок (5-8) второй диапазон — это [first2, last2).
1,5) Элементы сравниваются с помощью operator==.
3,7) Элементы сравниваются с помощью заданного бинарного предиката p.
2,4,6,8) То же, что и (1,3,5,7), но выполняется в соответствии с policy.
Эти перегрузки участвуют в разрешении перегрузки только если значение следующего выражения равно true:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(до C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(начиная с C++20)

Параметры

first1, last1 - пара итераторов, определяющая первый диапазон элементов для сравнения
first2, last2 - пара итераторов, определяющая второй диапазон элементов для сравнения
policy - политика выполнения для использования
p - бинарный предикат, который возвращает ​true если элементы следует считать равными.

Сигнатура функции предиката должна быть эквивалентна следующей:

bool pred(const Type1 &a, const Type2 &b);

Хотя сигнатура необязательно должна содержать const &, функция не должна изменять переданные ей объекты и должна быть способна принимать все значения типа (возможно, const) Type1 и Type2 независимо от категории значения (таким образом, Type1 & не разрешён, равно как и Type1 если только для Type1 перемещение не эквивалентно копированию(начиная с C++11)).
Типы Type1 и Type2 должны быть такими, что объекты типов InputIt1 и InputIt2 могут быть разыменованы и затем неявно преобразованы в Type1 и Type2 соответственно. ​

Требования к типам
-
InputIt1, InputIt2 должен соответствовать требованиям LegacyInputIterator.
-
ForwardIt1, ForwardIt2 должен соответствовать требованиям LegacyForwardIterator.
-
BinaryPred должен соответствовать требованиям BinaryPredicate.

Возвращаемое значение

1-4) Если каждый соответствующий элемент в двух диапазонах равен, возвращает true. В противном случае возвращает false.
5-8) Если std::distance(first1, last1) и std::distance(first2, last2) равны, и каждый соответствующий элемент в двух диапазонах равен, возвращает true. В противном случае возвращает false.

Сложность

Пусть N1 равно std::distance(first1, last1), а N2 равно std::distance(first2, last2):

1) Не более N1 сравнений с помощью operator==.
2) O(N1) сравнений с помощью operator==.
3) Не более N1 применений предиката p.
4) O(N1) применений предиката p.
5-8) Если InputIt1 и InputIt2 оба являются LegacyRandomAccessIterator, и last1 - first1 != last2 - first2 равно true, сравнение производиться не будет.
В противном случае, пусть N равно min(N1,N2):
5) Не более N сравнений с помощью operator==.
6) O(N) сравнений с помощью operator==.
7) Не более N применений предиката p.
8) O(N) применений предиката p.

Исключения

Перегрузки с параметром шаблона с именем ExecutionPolicy сообщают об ошибках следующим образом:

  • Если выполнение функции, вызванной как часть алгоритма, генерирует исключение и ExecutionPolicy является одной из стандартных политик, вызывается std::terminate. Для любой другой ExecutionPolicy поведение определяется реализацией.
  • Если алгоритму не удаётся выделить память, генерируется std::bad_alloc.

Возможная реализация

equal (1)
template<class InputIt1, class InputIt2>
constexpr //< since C++20
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
{
    for (; first1 != last1; ++first1, ++first2)
        if (!(*first1 == *first2))
            return false;
    
    return true;
}
equal (3)
template<class InputIt1, class InputIt2, class BinaryPred>
constexpr //< since C++20
bool equal(InputIt1 first1, InputIt1 last1,
           InputIt2 first2, BinaryPred p)
{
    for (; first1 != last1; ++first1, ++first2)
        if (!p(*first1, *first2))
            return false;
    
    return true;
}
equal (5)
namespace detail
{
    // random-access iterator implementation (allows quick range size detection)
    template<class RandomIt1, class RandomIt2>
    constexpr //< since C++20
    bool equal(RandomIt1 first1, RandomIt1 last1, RandomIt2 first2, RandomIt2 last2,
               std::random_access_iterator_tag, std::random_access_iterator_tag)
    {
        if (last1 - first1 != last2 - first2)
            return false;
        
        for (; first1 != last1; ++first1, ++first2)
            if (!(*first1 == *first2))
                return false;
        
        return true;
    }
    
    // input iterator implementation (needs to manually compare with “last2”)
    template<class InputIt1, class InputIt2>
    constexpr //< since C++20
    bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2,
               std::input_iterator_tag, std::input_iterator_tag)
    {
        for (; first1 != last1 && first2 != last2; ++first1, ++first2)
            if (!(*first1 == *first2))
                return false;
        
        return first1 == last1 && first2 == last2;
    }
}

template<class InputIt1, class InputIt2>
constexpr //< since C++20
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
{
    details::equal(first1, last1, first2, last2,
                   typename std::iterator_traits<InputIt1>::iterator_category(),
                   typename std::iterator_traits<InputIt2>::iterator_category());
}
equal (7)
namespace detail
{
    // random-access iterator implementation (allows quick range size detection)
    template<class RandomIt1, class RandomIt2, class BinaryPred>
    constexpr //< since C++20
    bool equal(RandomIt1 first1, RandomIt1 last1,
               RandomIt2 first2, RandomIt2 last2, BinaryPred p,
               std::random_access_iterator_tag, std::random_access_iterator_tag)
    {
        if (last1 - first1 != last2 - first2)
            return false;
        
        for (; first1 != last1; ++first1, ++first2)
            if (!p(*first1, *first2))
                return false;
        
        return true;
    }
    
    // input iterator implementation (needs to manually compare with “last2”)
    template<class InputIt1, class InputIt2, class BinaryPred>
    constexpr //< since C++20
    bool equal(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, InputIt2 last2, BinaryPred p,
               std::input_iterator_tag, std::input_iterator_tag)
    {
        for (; first1 != last1 && first2 != last2; ++first1, ++first2)
            if (!p(*first1, *first2))
                return false;
        
        return first1 == last1 && first2 == last2;
    }
}

template<class InputIt1, class InputIt2, class BinaryPred>
constexpr //< since C++20
bool equal(InputIt1 first1, InputIt1 last1,
           InputIt2 first2, InputIt2 last2, BinaryPred p)
{
    details::equal(first1, last1, first2, last2, p,
                   typename std::iterator_traits<InputIt1>::iterator_category(),
                   typename std::iterator_traits<InputIt2>::iterator_category());
}

Примечания

std::equal не следует использовать для сравнения диапазонов, образованных итераторами из std::unordered_set, std::unordered_multiset, std::unordered_map или std::unordered_multimap, поскольку порядок хранения элементов в этих контейнерах может различаться, даже если два контейнера хранят одни и те же элементы.

При сравнении целых контейнеров или строковых представлений(начиная с C++17) на равенство обычно предпочитают operator== для соответствующего типа.

Последовательная std::equal не гарантирует короткого замыкания. Например, если первые пары элементов обоих диапазонов не равны, остальные элементы также могут быть сравнены. Не-короткозамкнутое сравнение может происходить при сравнении диапазонов с помощью std::memcmp или реализационно-зависимых векторизованных алгоритмов.

Пример

Следующий код использует std::equal для проверки, является ли строка палиндромом.

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

constexpr bool is_palindrome(const std::string_view& s)
{
    return std::equal(s.cbegin(), s.cbegin() + s.size() / 2, s.crbegin());
}

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

int main()
{
    test("radar");
    test("hello");
}

Вывод:

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

Смотрите также

находит первый элемент, удовлетворяющий определённым критериям
(шаблон функции & функциональный объект алгоритма)
сравнивает два диапазона лексикографически
(шаблон функции & функциональный объект алгоритма)
находит первую позицию, где два диапазона различаются
(шаблон функции & функциональный объект алгоритма)
ищет первое вхождение диапазона элементов
(шаблон функции & функциональный объект алгоритма)
определяет, совпадают ли два набора элементов
(функциональный объект алгоритма)
функциональный объект, реализующий x == y
(шаблон класса)
находит диапазон элементов, соответствующих заданному значению, с помощью бинарного поиска
(шаблон функции & функциональный объект алгоритма)