Namespaces
Variants

std::ranges::equal_range

Depuis fr.cppreference.net
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur plages (C++20)
Algorithmes contraints, p.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)

Tri et opérations connexes
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


 
Algorithmes contraints
Tous les noms de ce menu appartiennent à l'espace de noms std::ranges
Opérations de séquence non modificatrices
Opérations de séquence modificatrices
Opérations de partitionnement
Opérations de tri
Opérations de recherche binaire (sur plages triées)
       
       
Opérations d'ensemble (sur plages triées)
Opérations de tas
Opérations de minimum/maximum
       
       
Opérations de permutation
Opérations de pliage
Opérations sur le stockage non initialisé
Types de retour
 
Défini dans l'en-tête <algorithm>
Signature d'appel
template< std::forward_iterator I, std::sentinel_for<I> S,
          class T, class Proj = std::identity,
          std::indirect_strict_weak_order
              <const T*, std::projected<I, Proj>> Comp = ranges::less >
constexpr ranges::subrange<I> equal_range( I first, S last, const T& value,
                                           Comp comp = {}, Proj proj = {} );
(1) (depuis C++20)
(jusqu'à C++26)
template< std::forward_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity,
          class T = std::projected_value_t<I, Proj>,
          std::indirect_strict_weak_order
              <const T*, std::projected<I, Proj>> Comp = ranges::less >
constexpr ranges::subrange<I> equal_range( I first, S last, const T& value,
                                           Comp comp = {}, Proj proj = {} );
(depuis C++26)
template< ranges::forward_range R,
          class T, class Proj = std::identity,
          std::indirect_strict_weak_order
              <const T*, std::projected<ranges::iterator_t<R>,
                                        Proj>> Comp = ranges::less >
constexpr ranges::borrowed_subrange_t<R>
    equal_range( R&& r, const T& value, Comp comp = {}, Proj proj = {} );
(2) (depuis C++20)
(jusqu'à C++26)
template< ranges::forward_range R,
          class Proj = std::identity,
          class T = std::projected_value_t<ranges::iterator_t<R>, Proj>,
          std::indirect_strict_weak_order
              <const T*, std::projected<ranges::iterator_t<R>,
                                        Proj>> Comp = ranges::less >
constexpr ranges::borrowed_subrange_t<R>
    equal_range( R&& r, const T& value, Comp comp = {}, Proj proj = {} );
(depuis C++26)
1) Renvoie une vue contenant tous les éléments équivalents à value dans la plage [firstlast).

La plage [firstlast) doit être au moins partiellement ordonnée par rapport à value, c'est-à-dire qu'elle doit satisfaire à toutes les exigences suivantes :

  • partitionnée par rapport à element < value ou comp(element, value) (c'est-à-dire que tous les éléments pour lesquels l'expression est true précèdent tous les éléments pour lesquels l'expression est false).
  • partitionnée par rapport à !(value < element) ou !comp(value, element).
  • pour tous les éléments, si element < value ou comp(element, value) est true alors !(value < element) ou !comp(value, element) est également true.

Une plage complètement triée répond à ces critères.

La vue renvoyée est construite à partir de deux itérateurs, l'un pointant vers le premier élément qui est pas inférieur à value et un autre pointant vers le premier élément plus grand que value. Le premier itérateur peut également être obtenu avec std::ranges::lower_bound(), le second avec std::ranges::upper_bound().

2) Identique à (1), mais utilise r comme plage source, comme si la plage ranges::begin(r) était utilisée comme first et ranges::end(r) comme last.

Les entités de type fonction décrites sur cette page sont des objets fonctions d'algorithme (informellement appelés niebloids), c'est-à-dire :

Paramètres

first, last - la paire itérateur-sentinelle définissant la plage d'éléments à examiner
r - la plage d'éléments à examiner
value - valeur à comparer aux éléments
comp - si le premier argument est inférieur au second (c'est-à-dire s'il est ordonné avant)
proj - projection à appliquer aux éléments

Valeur de retour

std::ranges::subrange contenant une paire d'itérateurs définissant la plage souhaitée, le premier pointant vers le premier élément qui est pas inférieur à value et le second pointant vers le premier élément plus grand que value.

S'il n'y a aucun élément pas inférieur à value, le dernier itérateur (itérateur égal à last ou ranges::end(r)) est renvoyé comme premier élément. De même, s'il n'y a aucun élément plus grand que value, le dernier itérateur est renvoyé comme deuxième élément.

Complexité

Le nombre de comparaisons effectuées est logarithmique par rapport à la distance entre first et last (au plus 2 * log2(last - first) + O(1) comparaisons). Cependant, pour un itérateur qui ne modélise pas random_access_iterator, le nombre d'incréments d'itérateur est linéaire.

Implémentation possible

struct equal_range_fn
{
    template<std::forward_iterator I, std::sentinel_for<I> S,
             class Proj = std::identity, class T = std::projected_value_t<I, Proj>,
             std::indirect_strict_weak_order
                 <const T*, std::projected<I, Proj>> Comp = ranges::less>
    constexpr ranges::subrange<I>
        operator()(I first, S last, const T& value, Comp comp = {}, Proj proj = {}) const
    {
        return ranges::subrange
        (
            ranges::lower_bound(first, last, value, std::ref(comp), std::ref(proj)),
            ranges::upper_bound(first, last, value, std::ref(comp), std::ref(proj))
        );
    }
 
    template<ranges::forward_range R, class Proj = std::identity,
             class T = std::projected_value_t<ranges::iterator_t<R>, Proj>,
             std::indirect_strict_weak_order
                 <const T*, std::projected<ranges::iterator_t<R>,
                                           Proj>> Comp = ranges::less>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, const T& value, Comp comp = {}, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), value,
                       std::ref(comp), std::ref(proj));
    }
};
 
inline constexpr equal_range_fn equal_range;

Notes

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

Exemple

#include <algorithm>
#include <compare>
#include <complex>
#include <iostream>
#include <vector>

struct S
{
    int number {};
    char name {};
    // note: name is ignored by these comparison operators
    friend bool operator== (const S s1, const S s2) { return s1.number == s2.number; }
    friend auto operator<=>(const S s1, const S s2) { return s1.number <=> s2.number; }
    friend std::ostream& operator<<(std::ostream& os, S o)
    {
        return os << '{' << o.number << ", '" << o.name << "'}";
    }
};

void println(auto rem, const auto& v)
{
    for (std::cout << rem; const auto& e : v)
        std::cout << e << ' ';
    std::cout << '\n';
}

int main()
{
    // note: not ordered, only partitioned w.r.t. S defined below
    std::vector<S> vec
    {
        {1,'A'}, {2,'B'}, {2,'C'}, {2,'D'}, {4, 'D'}, {4,'G'}, {3,'F'}
    };
    
    const S value{2, '?'};
    
    namespace ranges = std::ranges;
    
    auto a = ranges::equal_range(vec, value);
    println("1. ", a);
    
    auto b = ranges::equal_range(vec.begin(), vec.end(), value);
    println("2. ", b);
    
    auto c = ranges::equal_range(vec, 'D', ranges::less {}, &S::name);
    println("3. ", c);
    
    auto d = ranges::equal_range(vec.begin(), vec.end(), 'D', ranges::less {}, &S::name);
    println("4. ", d);

    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 = ranges::equal_range(nums, {2, 0}, cmpz);
    #else
        auto p3 = ranges::equal_range(nums, CD{2, 0}, cmpz);
    #endif
    println("5. ", p3);
}

Sortie :

1. {2, 'B'} {2, 'C'} {2, 'D'}
2. {2, 'B'} {2, 'C'} {2, 'D'}
3. {2, 'D'} {4, 'D'}
4. {2, 'D'} {4, 'D'}
5. (2,2) (2,1)

Voir aussi

trouve le premier élément non inférieur à la valeur donnée en utilisant la recherche binaire
(objet fonction d'algorithme)
trouve le premier élément supérieur à la valeur donnée en utilisant la recherche binaire
(objet fonction d'algorithme)
détermine si un élément existe dans une plage en utilisant la recherche binaire
(objet fonction d'algorithme)
divise une plage d'éléments en deux groupes
(objet fonction d'algorithme)
détermine si deux ensembles d'éléments sont identiques
(objet fonction d'algorithme)
trouve la plage d'éléments correspondant à la valeur donnée en utilisant la recherche binaire
(fonction template)