std:: equal_range
|
Определено в заголовке
<algorithm>
|
||
| (1) | ||
|
template
<
class
ForwardIt,
class
T
>
std::
pair
<
ForwardIt, ForwardIt
>
|
(constexpr начиная с C++20)
(до C++26) |
|
|
template
<
class
ForwardIt,
class
T
=
typename
std::
iterator_traits
<
ForwardIt
>
::
value_type
>
|
(начиная с C++26) | |
| (2) | ||
|
template
<
class
ForwardIt,
class
T,
class
Compare
>
std::
pair
<
ForwardIt, ForwardIt
>
|
(constexpr начиная с C++20)
(до C++26) |
|
|
template
<
class
ForwardIt,
class
T
=
typename
std::
iterator_traits
<
ForwardIt
>
::
value_type
,
|
(начиная с C++26) | |
Возвращает диапазон, содержащий все элементы, эквивалентные
value
в разделённом диапазоне
[
first
,
last
)
.
|
Возвращает результаты std:: lower_bound ( first, last, value ) и std:: upper_bound ( first, last, value ) . Если выполняется любое из следующих условий, поведение не определено:
|
(до C++20) |
|
Эквивалентно std :: equal_range ( first, last, value, std:: less { } ) . |
(начиная с C++20) |
-
Для любого элемента
elem
из
[first,last), bool ( comp ( elem, value ) ) не влечёт ! bool ( comp ( value, elem ) ) . -
Элементы
elem
из
[first,last)не являются partitioned относительно выражений bool ( comp ( elem, value ) ) и ! bool ( comp ( value, elem ) ) .
Содержание |
Параметры
| first, last | - | пара итераторов, определяющих разделённый диапазон элементов для проверки |
| value | - | значение для сравнения с элементами |
| comp | - |
бинарный предикат, который возвращает
true
если первый аргумент упорядочен перед вторым.
Сигнатура функции-предиката должна быть эквивалентна следующей: bool pred ( const Type1 & a, const Type2 & b ) ;
Хотя сигнатура не обязана содержать
const
&
, функция не должна модифицировать передаваемые ей объекты и должна быть способна принимать все значения типа (возможно const)
|
| Требования к типам | ||
-
ForwardIt
должен удовлетворять требованиям
LegacyForwardIterator
.
|
||
-
Compare
должен удовлетворять требованиям
BinaryPredicate
. Не требуется удовлетворять
Compare
.
|
||
Возвращаемое значение
Объект std::pair содержащий пару итераторов, где
-
firstявляется итератором на первый элемент диапазона[first,last)не упорядоченный перед value (или last если такой элемент не найден), и -
secondявляется итератором на первый элемент диапазона[first,last)упорядоченный после value (или last если такой элемент не найден).
Сложность
Дано N как std:: distance ( first, last ) :
Однако, если
ForwardIt
не является
LegacyRandomAccessIterator
, количество инкрементов итератора линейно зависит от
N
. В частности, итераторы
std::set
и
std::multiset
не являются итераторами произвольного доступа, поэтому их функции-члены
std::set::equal_range
(соотв.
std::multiset::equal_range
) должны быть предпочтительны.
Примечания
Хотя
std::equal_range
требует только, чтобы диапазон
[
first
,
last
)
был разделён, этот алгоритм обычно используется в случае, когда
[
first
,
last
)
отсортирован, чтобы бинарный поиск был корректным для любого
value
.
В дополнение к требованиям
std::lower_bound
и
std::upper_bound
,
std::equal_range
также требует, чтобы
operator
<
или
comp
были асимметричными (т.е.,
a
<
b
и
b
<
a
всегда имеют различные результаты).
Следовательно, промежуточные результаты бинарного поиска могут быть использованы совместно
std::lower_bound
и
std::upper_bound
. Например, результат вызова
std::lower_bound
может быть использован в качестве аргумента
first
в вызове
std::upper_bound
.
| Макрос тестирования возможностей | Значение | Стандарт | Возможность |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type
|
202403
|
(C++26) | Списковая инициализация для алгоритмов ( 1,2 ) |
Возможная реализация
| equal_range (1) |
|---|
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type> constexpr std::pair<ForwardIt, ForwardIt> equal_range(ForwardIt first, ForwardIt last, const T& value) { return std::equal_range(first, last, value, std::less{}); } |
| equal_range (2) |
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type, class Compare> constexpr std::pair<ForwardIt, ForwardIt> equal_range(ForwardIt first, ForwardIt last, const T& value, Compare comp) { return std::make_pair(std::lower_bound(first, last, value, comp), std::upper_bound(first, last, value, comp)); } |
` и `` оставлен без изменений, как и требовалось. HTML-теги и атрибуты также сохранены в оригинальном виде.
Пример
#include <algorithm> #include <complex> #include <iostream> #include <vector> struct S { int number; char name; // примечание: name игнорируется этим оператором сравнения bool operator<(const S& s) const { return number < s.number; } }; struct Comp { bool operator()(const S& s, int i) const { return s.number < i; } bool operator()(int i, const S& s) const { return i < s.number; } }; int main() { // примечание: не отсортировано, только разделено относительно S, определенного ниже const std::vector<S> vec{{1, 'A'}, {2, 'B'}, {2, 'C'}, {2, 'D'}, {4, 'G'}, {3, 'F'}}; const S value{2, '?'}; std::cout << "Сравнение с использованием S::operator<(): "; const auto p = std::equal_range(vec.begin(), vec.end(), value); for (auto it = p.first; it != p.second; ++it) std::cout << it->name << ' '; std::cout << '\n'; std::cout << "Использование гетерогенного сравнения: "; const auto p2 = std::equal_range(vec.begin(), vec.end(), 2, Comp{}); for (auto it = p2.first; it != p2.second; ++it) std::cout << it->name << ' '; std::cout << '\n'; using CD = std::complex<double>; std::vector<CD> nums{{1, 0}, {2, 2}, {2, 1}, {3, 0}, {3, 1}}; auto cmpz = [](CD x, CD y) { return x.real() < y.real(); }; #ifdef __cpp_lib_algorithm_default_value_type auto p3 = std::equal_range(nums.cbegin(), nums.cend(), {2, 0}, cmpz); #else auto p3 = std::equal_range(nums.cbegin(), nums.cend(), CD{2, 0}, cmpz); #endif for (auto it = p3.first; it != p3.second; ++it) std::cout << *it << ' '; std::cout << '\n'; }
Вывод:
Compare using S::operator<(): B C D Using heterogeneous comparison: B C D (2,2) (2, 1)
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение в опубликованной версии | Корректное поведение |
|---|---|---|---|
| LWG 270 | C++98 |
Compare
требовалось удовлетворять
Compare
и
T
требовалось
быть LessThanComparable (требовался строгий слабый порядок) |
требуется только разделение;
разрешены гетерогенные сравнения |
| LWG 384 | C++98 |
допускалось не более
2log
2
(N)+1
сравнений
что не реализуемо [1] |
исправлено на 2log 2 (N)+O(1) |
-
↑
Применение
equal_rangeк диапазону с одним элементом требует 2 сравнений, но по требованию сложности допускается не более 1 сравнения.
Смотрите также
|
возвращает итератор на первый элемент
не меньший
заданного значения
(шаблон функции) |
|
|
возвращает итератор на первый элемент
больший
заданного значения
(шаблон функции) |
|
|
определяет, существует ли элемент в частично упорядоченном диапазоне
(шаблон функции) |
|
|
разделяет диапазон элементов на две группы
(шаблон функции) |
|
|
определяет, идентичны ли два набора элементов
(шаблон функции) |
|
|
возвращает диапазон элементов, соответствующих заданному ключу
(публичная функция-член
std::set<Key,Compare,Allocator>
)
|
|
|
возвращает диапазон элементов, соответствующих заданному ключу
(публичная функция-член
std::multiset<Key,Compare,Allocator>
)
|
|
|
(C++20)
|
возвращает диапазон элементов, соответствующих заданному ключу
(функциональный объект алгоритма) |