Namespaces
Variants

std::ranges:: 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)
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
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations (on sorted ranges)
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Permutation operations
Fold operations
Operations on uninitialized storage
Return types
Défini dans l'en-tête <algorithm>
Signature d'appel
(1)
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 = { } ) ;
(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)
(2)
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 = { } ) ;
(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 l'intervalle [ first , last ) .

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

  • partitionné 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é 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 entièrement triée répond à ces critères.

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

2) Identique à (1) , mais utilise r comme plage source, comme si on utilisait ranges:: begin ( r ) comme first et ranges:: end ( r ) comme last .

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

Table des matières

Paramètres

first, last - la paire itérateur-sentinelle définissant la plage des éléments à examiner
r - la plage des éléments à examiner
value - valeur à comparer aux éléments
comp - si le premier argument est inférieur au second (c'est-à-dire 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 n'est pas inférieur à value et le second pointant vers le premier élément supérieur à value .

S'il n'y a aucun élément non inférieur à value , le dernier itérateur (itérateur égal à last ou ranges:: end ( r ) ) est retourné comme premier élément. De même, s'il n'y a aucun élément supérieur à value , le dernier itérateur est retourné comme second élément.

Complexité

Le nombre de comparaisons effectuées est logarithmique par rapport à la distance entre first et last (au plus 2 * log 2 (last - first) + O(1) comparaisons). Cependant, pour un itérateur qui ne modélise pas random_access_iterator , le nombre d'incrémentations 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 par 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

retourne un itérateur vers le premier élément non inférieur à la valeur donnée
(objet fonction algorithme)
retourne un itérateur vers le premier élément supérieur à une certaine valeur
(objet fonction algorithme)
détermine si un élément existe dans une plage partiellement ordonnée
(objet fonction algorithme)
divise une plage d'éléments en deux groupes
(objet fonction algorithme)
détermine si deux ensembles d'éléments sont identiques
(objet fonction algorithme)
retourne la plage d'éléments correspondant à une clé spécifique
(modèle de fonction)