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
(Anmerkung: Der bereitgestellte HTML-Code enthält keinen übersetzbaren Text, da alle Tags leer sind. Die HTML-Struktur wurde gemäß den Anforderungen unverändert beibehalten.)
Definiert im Header <algorithm>
Aufrufsignatur
(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 = { } ) ;
(seit C++20)
(bis 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 = { } ) ;
(seit 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 = { } ) ;
(seit C++20)
(bis 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 = { } ) ;
(seit C++26)
1) Gibt eine Ansicht zurück, die alle Elemente enthält, die in dem Bereich [ first , last ) dem Wert value entsprechen.

Der Bereich [ first , last ) muss mindestens teilweise geordnet sein in Bezug auf value , d.h. er muss alle folgenden Anforderungen erfüllen:

  • partitioniert in Bezug auf element < value oder comp ( element, value ) (d.h. alle Elemente, für die der Ausdruck true ist, stehen vor allen Elementen, für die der Ausdruck false ist).
  • partitioniert in Bezug auf ! ( value < element ) oder ! comp ( value, element ) .
  • für alle Elemente gilt: wenn element < value oder comp ( element, value ) true ist, dann ist auch ! ( value < element ) oder ! comp ( value, element ) true .

Ein vollständig sortierter Bereich erfüllt diese Kriterien.

Die zurückgegebene Ansicht wird aus zwei Iteratoren konstruiert, wobei einer auf das erste Element zeigt, das nicht kleiner als value ist, und ein anderer auf das erste Element zeigt, das größer als value ist. Der erste Iterator kann alternativ mit std::ranges::lower_bound() erhalten werden, der zweite - mit std::ranges::upper_bound() .

2) Gleich wie (1) , verwendet jedoch r als Quellbereich, als würde der Bereich ranges:: begin ( r ) als first und ranges:: end ( r ) als last verwendet.

Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithm Function Objects (informell bekannt als Niebloids ), das heißt:

Inhaltsverzeichnis

Parameter

first, last - das Iterator-Sentinel-Paar, das den Bereich der zu untersuchenden Elemente definiert
r - der Bereich der zu untersuchenden Elemente
value - Wert, mit dem die Elemente verglichen werden
comp - ob das erste Argument kleiner als das zweite ist (d.h. vor diesem geordnet ist)
proj - Projektion, die auf die Elemente angewendet wird

Rückgabewert

std::ranges::subrange enthaltend ein Paar von Iteratoren, die den gewünschten Bereich definieren, wobei der erste auf das erste Element zeigt, das nicht kleiner als value ist, und der zweite auf das erste Element zeigt, das größer als value ist.

Wenn keine Elemente vorhanden sind, die nicht kleiner als value sind, wird der letzte Iterator (Iterator, der gleich last oder ranges:: end ( r ) ist) als erstes Element zurückgegeben. Ebenso wird, wenn keine Elemente größer als value vorhanden sind, der letzte Iterator als zweites Element zurückgegeben.

Komplexität

Die Anzahl der durchgeführten Vergleiche ist logarithmisch im Abstand zwischen first und last (höchstens 2 * log 2 (last - first) + O(1) Vergleiche). Für einen Iterator, der nicht random_access_iterator modelliert, ist die Anzahl der Iterator-Inkremente jedoch linear.

Mögliche Implementierung

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;

Hinweise

Feature-Test Makro Wert Std Funktion
__cpp_lib_algorithm_default_value_type 202403 (C++26) Listeninitialisierung für Algorithmen ( 1,2 )

Beispiel

#include <algorithm>
#include <compare>
#include <complex>
#include <iostream>
#include <vector>
struct S
{
    int number {};
    char name {};
    // Hinweis: name wird von diesen Vergleichsoperatoren ignoriert
    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()
{
    // Hinweis: nicht sortiert, nur partitioniert bezüglich unten definiertem S
    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);
}

Ausgabe:

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)

Siehe auch

gibt einen Iterator zum ersten Element zurück, das nicht kleiner als der gegebene Wert ist
(Algorithmus-Funktionsobjekt)
gibt einen Iterator zum ersten Element zurück, das größer als ein bestimmter Wert ist
(Algorithmus-Funktionsobjekt)
bestimmt, ob ein Element in einem teilweise geordneten Bereich existiert
(Algorithmus-Funktionsobjekt)
unterteilt einen Elementbereich in zwei Gruppen
(Algorithmus-Funktionsobjekt)
bestimmt, ob zwei Elementmengen identisch sind
(Algorithmus-Funktionsobjekt)
gibt den Bereich der Elemente zurück, die einem spezifischen Schlüssel entsprechen
(Funktionstemplate)