Namespaces
Variants

std:: equal_range

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
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
Sorting operations
Binary search operations
(on partitioned ranges)
equal_range
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Défini dans l'en-tête <algorithm>
(1)
template < class ForwardIt, class T >

std:: pair < ForwardIt, ForwardIt >

equal_range ( ForwardIt first, ForwardIt last, const T & value ) ;
(constexpr depuis C++20)
(jusqu'à C++26)
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 ) ;
(depuis C++26)
(2)
template < class ForwardIt, class T, class Compare >

std:: pair < ForwardIt, ForwardIt >
equal_range ( ForwardIt first, ForwardIt last,

const T & value, Compare comp ) ;
(constexpr depuis C++20)
(jusqu'à C++26)
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 ) ;
(depuis C++26)

Retourne une plage contenant tous les éléments équivalents à value dans la plage partitionnée [ first , last ) .

1) L'équivalence est vérifiée en utilisant operator < :

Retourne les résultats de std:: lower_bound ( first, last, value ) et std:: upper_bound ( first, last, value ) .

Si l'une des conditions suivantes est satisfaite, le comportement est indéfini :

  • Pour tout élément elem de [ first , last ) , bool ( elem < value ) n'implique pas ! bool ( value < elem ) .
  • Les éléments elem de [ first , last ) ne sont pas partitionnés par rapport aux expressions bool ( elem < value ) et ! bool ( value < elem ) .
(jusqu'à C++20)

Équivalent à std :: equal_range ( first, last, value, std:: less { } ) .

(depuis C++20)
2) L'équivalence est vérifiée en utilisant comp :
Retourne les résultats de std:: lower_bound ( first, last, value, comp ) et de std:: upper_bound ( first, last, value, comp ) .
Si l'une des conditions suivantes est satisfaite, le comportement est indéfini :
  • Pour tout élément elem de [ first , last ) , bool ( comp ( elem, value ) ) n'implique pas ! bool ( comp ( value, elem ) ) .
  • Les éléments elem de [ first , last ) ne sont pas partitionnés par rapport aux expressions bool ( comp ( elem, value ) ) et ! bool ( comp ( value, elem ) ) .

Table des matières

Paramètres

first, last - la paire d'itérateurs définissant la plage partitionnée des éléments à examiner
value - valeur à comparer aux éléments
comp - prédicat binaire qui renvoie ​ true si le premier argument est ordonné avant le second.

La signature de la fonction de prédicat doit être équivalente à ce qui suit :

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

Bien que la signature n'ait pas besoin d'avoir const & , la fonction ne doit pas modifier les objets qui lui sont passés et doit pouvoir accepter toutes les valeurs de type (éventuellement const) Type1 et Type2 indépendamment de la catégorie de valeur (ainsi, Type1 & n'est pas autorisé , pas plus que Type1 sauf si pour Type1 un déplacement équivaut à une copie (depuis C++11) ).
Les types Type1 et Type2 doivent être tels qu'un objet de type T puisse être implicitement converti à la fois en Type1 et en Type2 , et qu'un objet de type ForwardIt puisse être déréférencé puis implicitement converti à la fois en Type1 et en Type2 . ​

Exigences de type
-
ForwardIt doit satisfaire aux exigences de LegacyForwardIterator .
-
Compare doit satisfaire aux exigences de BinaryPredicate . Il n'est pas requis de satisfaire Compare .

Valeur de retour

Un std::pair contenant une paire d'itérateurs, où

  • first est un itérateur vers le premier élément de la plage [ first , last ) non ordonné avant value (ou last si aucun tel élément n'est trouvé), et
  • second est un itérateur vers le premier élément de la plage [ first , last ) ordonné après value (ou last si aucun tel élément n'est trouvé).

Complexité

Étant donné N comme std:: distance ( first, last ) :

1) Au maximum 2log 2 (N)+O(1) comparaisons avec value en utilisant operator < (jusqu'à C++20) std:: less { } (depuis C++20) .
2) Au plus 2log 2 (N)+O(1) applications du comparateur comp .

Cependant, si ForwardIt n'est pas un LegacyRandomAccessIterator , le nombre d'incrémentations d'itérateur est linéaire en N . Notamment, les itérateurs de std::set et std::multiset ne sont pas à accès aléatoire, et donc leurs fonctions membres std::set::equal_range (resp. std::multiset::equal_range ) devraient être préférées.

Notes

Bien que std::equal_range ne nécessite que [ first , last ) soit partitionné, cet algorithme est généralement utilisé dans le cas où [ first , last ) est trié, de sorte que la recherche binaire soit valide pour toute value .

En plus des exigences de std::lower_bound et std::upper_bound , std::equal_range requiert également que operator < ou comp soit asymétrique (c'est-à-dire que a < b et b < a aient toujours des résultats différents).

Par conséquent, les résultats intermédiaires de la recherche binaire peuvent être partagés par std::lower_bound et std::upper_bound . Par exemple, le résultat de l'appel à std::lower_bound peut être utilisé comme argument de first dans l'appel à std::upper_bound .

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_lib_algorithm_default_value_type 202403 (C++26) Initialisation par liste pour les algorithmes ( 1,2 )

Implémentation possible

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

Exemple

#include <algorithm>
#include <complex>
#include <iostream>
#include <vector>
struct S
{
    int number;
    char name;
    // note: name is ignored by this comparison operator
    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()
{
    // note: not ordered, only partitioned w.r.t. S defined below
    const std::vector<S> vec{{1, 'A'}, {2, 'B'}, {2, 'C'},
                             {2, 'D'}, {4, 'G'}, {3, 'F'}};
    const S value{2, '?'};
    std::cout << "Compare using 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 << "Using heterogeneous comparison: ";
    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';
}

Sortie :

Compare using S::operator<(): B C D 
Using heterogeneous comparison: B C D
(2,2) (2, 1)

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement corrigé
LWG 270 C++98 Compare devait satisfaire Compare et T devait
être LessThanComparable (ordre faible strict requis)
seul un partitionnement est requis ;
comparaisons hétérogènes autorisées
LWG 384 C++98 au plus 2log 2 (N)+1 comparaisons
étaient autorisées, ce qui n'est pas implémentable [1]
corrigé en 2log 2 (N)+O(1)
  1. L'application de equal_range à une plage d'éléments uniques nécessite 2 comparaisons, mais au plus 1 comparaison est autorisée par l'exigence de complexité.

Voir aussi

renvoie un itérateur vers le premier élément non inférieur à la valeur donnée
(modèle de fonction)
renvoie un itérateur vers le premier élément supérieur à une certaine valeur
(modèle de fonction)
détermine si un élément existe dans une plage partiellement ordonnée
(modèle de fonction)
divise une plage d'éléments en deux groupes
(modèle de fonction)
détermine si deux ensembles d'éléments sont identiques
(modèle de fonction)
renvoie la plage d'éléments correspondant à une clé spécifique
(fonction membre publique de std::set<Key,Compare,Allocator> )
renvoie la plage d'éléments correspondant à une clé spécifique
(fonction membre publique de std::multiset<Key,Compare,Allocator> )
renvoie la plage d'éléments correspondant à une clé spécifique
(objet fonction algorithme)