Spec-Zone.ru › C++

std::ranges::equal

Определён в заголовочном файле <algorithm>
Сигнатура вызова
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) (начиная с 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) (начиная с 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) (начиная с 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) (начиная с C++26)

Определение /*execution-policy*/ см. на этой странице; определение /*sized-random-access-range*/ см. на этой странице.

Проверяет, равны ли два целевых диапазона. Элементы (спроецированные соответственно с помощью proj1 и proj2) сравниваются с использованием бинарного предиката pred.

1) Целевыми диапазонами являются [first1, last1) и [first2, last2).
2) Целевыми диапазонами являются r1 и r2.
3,4) Аналогично (1,2), но выполняется в соответствии с policy.

Описанные на этой странице функциональные сущности являются объектами-функциями алгоритмов (неформально называемыми niebloids), то есть:

  • При вызове любой из них нельзя указывать явный список аргументов шаблона.
  • Ни одна из них не видна для поиска, зависящего от аргументов.
  • Если какая-либо из них найдена посредством обычного неквалифицированного поиска в качестве имени слева от оператора вызова функции, поиск, зависящий от аргументов, подавляется.

Параметры

first1, last1 - пара итератора и сентинела, задающая первый целевой диапазон
r1 - первый целевой диапазон
first2, last2 - пара итератора и сентинела, задающая второй целевой диапазон
r2 - второй целевой диапазон
pred - предикат, применяемый к (спроецированным) элементам
proj1 - проекция, применяемая к элементам первого целевого диапазона
proj2 - проекция, применяемая к элементам второго целевого диапазона

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

Если размеры двух целевых диапазонов одинаковы и каждый соответствующий (спроецированный) элемент в обоих диапазонах равен другому, возвращает true. В противном случае возвращает false.

Сложность

Пусть

  • \(\scriptsize N_1\)N1 обозначает ranges::distance(first1, last1) или ranges::distance(r1), а
  • \(\scriptsize N_2\)N2 обозначает ranges::distance(first2, last2) или ranges::distance(r2):
1,2) Не более \(\scriptsize \min(N_1,N_2)\)min(N1,N2) применений pred, proj1 и proj2.
3,4) \(\scriptsize \mathcal{O}(\min(N_1,N_2))\)𝓞(min(N1,N2)) применений pred, proj1 и proj2.

Если I1, S1, I2 и S2 попарно моделируют sized_sentinel_for (или оба R1 и R2 моделируют sized_range), а \(\scriptsize N_1 \neq N_2\)N1≠N2, сравнения выполняться не будут.

Исключения

3,4) В ходе выполнения:
  • Если необходимые для распараллеливания временные ресурсы памяти недоступны, выбрасывается std::bad_alloc.
  • Если при доступе к объектам через аргумент алгоритма выбрасывается неперехваченное исключение, поведение определяется политикой выполнения (для стандартных политик вызывается std::terminate).

Примечания

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

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

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

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

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;

Пример

В приведённом ниже коде используется ranges::equal, чтобы проверить, является ли строка палиндромом.

#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"));
}

Вывод:

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

См. также

equal
определяет, одинаковы ли два набора элементов
(шаблон функции)
ranges::findranges::find_ifranges::find_if_not
(C++20)(C++20)(C++20)
находит первый элемент, удовлетворяющий заданным критериям
(объект-функция алгоритма)
ranges::lexicographical_compare
(C++20)
сравнивает два диапазона лексикографически
(объект-функция алгоритма)
ranges::mismatch
(C++20)
находит первую позицию, в которой различаются два диапазона
(объект-функция алгоритма)
ranges::search
(C++20)
ищет первое вхождение диапазона элементов
(объект-функция алгоритма)
ranges::equal_range
(C++20)
находит диапазон элементов, соответствующих заданному значению, с помощью двоичного поиска
(объект-функция алгоритма)
equal_to
объект-функция, реализующий x == y
(шаблон класса)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/algorithm/ranges/equal

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API