Namespaces
Variants

std::equal_range

Depuis fr.cppreference.net
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur plages (C++20)
Algorithmes contraints, par ex. ranges::copy, ranges::sort, ...
Opérations de séquence non modificatrices    
Opérations par lots
(C++17)
Opérations de recherche
Opérations de séquence modificatrices
Opérations de copie
(C++11)
(C++11)
Opérations d'échange
Opérations de transformation
Opérations de génération
Opérations de suppression
Opérations de changement d'ordre
(jusqu'à C++17)(C++11)
(C++20)(C++20)
Opérations d'échantillonnage
(C++17)

Opérations de tri et apparentées
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur plages partitionnées)
Opérations d'ensemble (sur plages triées)
Opérations de fusion (sur plages triées)
Opérations de tas
Opérations de minimum/maximum
(C++11)
(C++17)
Opérations de comparaison lexicographique
Opérations de permutation


 
Défini dans l'en-tête <algorithm>
template< class ForwardIt, class T >
std::pair<ForwardIt, ForwardIt> 
    equal_range( ForwardIt first, ForwardIt last, const T& value );
(1) (jusqu'à C++26)
(constexpr depuis C++20)
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)
template< class ForwardIt, class T, class Compare >
std::pair<ForwardIt, ForwardIt> 
    equal_range( ForwardIt first, ForwardIt last,
                 const T& value, Compare comp );
(2) (jusqu'à C++26)
(constexpr depuis C++20)
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 [firstlast).

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 [firstlast), bool(elem < value) n'implique pas !bool(value < elem).
  • Les éléments elem de [firstlast) 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 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 [firstlast), bool(comp(elem, value)) n'implique pas !bool(comp(value, elem)).
  • Les éléments elem de [firstlast) ne sont pas partitionnés par rapport aux expressions bool(comp(elem, value)) et !bool(comp(value, elem)).

Paramètres

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

La signature de la fonction prédicat doit être équivalente à la suivante :

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 quelle que soit la catégorie de valeur (ainsi, Type1 & n'est pas autorisé, non 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 Type2, et qu'un objet de type ForwardIt puisse être déréférencé puis implicitement converti à la fois en Type1 et Type2.

Exigences de type
-
ForwardIt doit satisfaire les exigences de LegacyForwardIterator.
-
Compare doit satisfaire les exigences de BinaryPredicate. Il n'est pas nécessaire qu'il satisfasse 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 [firstlast) non ordonné avant value (ou last si aucun élément de ce type n'est trouvé), et
  • second est un itérateur vers le premier élément de la plage [firstlast) ordonné après value (ou last si aucun élément de ce type n'est trouvé).

Complexité

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

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

Cependant, si ForwardIt n'est pas un LegacyRandomAccessIterator, le nombre d'incréments 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, donc leurs fonctions membres std::set::equal_range (resp. std::multiset::equal_range) doivent être préférées.

Notes

Bien que std::equal_range exige seulement que [firstlast) soit partitionnée, cet algorithme est généralement utilisé dans le cas où [firstlast) est triée, afin que la recherche binaire soit valide pour toute value.

En plus des exigences de std::lower_bound et std::upper_bound, std::equal_range exige é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 tel que publié Comportement correct
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 2log2(N)+1 comparaisons
étaient autorisées, ce qui n'est pas implémentable[1]
corrigé en 2log2(N)+O(1)
  1. Appliquer equal_range à une plage d'un seul élément nécessite 2 comparaisons, mais au plus 1 comparaison est autorisée par l'exigence de complexité.

Voir aussi

trouve le premier élément non inférieur à la valeur donnée en utilisant la recherche binaire
(gabarit de fonction & objet fonction d'algorithme)
trouve le premier élément supérieur à la valeur donnée en utilisant la recherche binaire
(gabarit de fonction & objet fonction d'algorithme)
détermine si un élément existe dans une plage en utilisant la recherche binaire
(gabarit de fonction & objet fonction d'algorithme)
divise une plage d'éléments en deux groupes
(gabarit de fonction & objet fonction d'algorithme)
détermine si deux ensembles d'éléments sont identiques
(gabarit de fonction & objet fonction d'algorithme)
retourne une plage d'éléments correspondant à une clé spécifique
(fonction membre publique de std::set<Key,Compare,Allocator>)
retourne une plage d'éléments correspondant à une clé spécifique
(fonction membre publique de std::multiset<Key,Compare,Allocator>)
trouve la plage d'éléments correspondant à la valeur donnée en utilisant la recherche binaire
(objet fonction d'algorithme)