名前空間
変種
操作

std::ranges::equal_range

From cppreference.com
< cpp‎ | algorithm‎ | ranges
 
 
アルゴリズムライブラリ
制約付きアルゴリズムとRangeアルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy, ranges::sort, ...
実行ポリシー (C++17)
シーケンスを変更しない操作
一括操作
(C++17)
検索操作
(C++11)                (C++11)(C++11)

シーケンスを変更する操作
コピー操作
(C++11)
(C++11)
スワップ操作
変換操作
生成操作
削除操作
順序変更操作
(C++17まで)(C++11)
(C++20)(C++20)
サンプリング操作
(C++17)

ソートおよび関連操作
パーティション操作
ソート操作
二分探索操作
(パーティション化された範囲)
集合操作 (ソート済み範囲)
マージ操作 (ソート済み範囲)
ヒープ操作
最小/最大操作
(C++11)
(C++17)
辞書順比較操作
順列操作
Cライブラリ
数値演算
未初期化メモリに対する操作
 
制約付きアルゴリズム
このメニューのすべての名前は名前空間 `std::ranges` に属します
シーケンスを変更しない操作
シーケンスを変更する操作
パーティション操作
ソート操作
二分探索操作 (ソート済み範囲)
       
       
equal_range
集合操作 (ソート済み範囲)
ヒープ操作
最小/最大操作
       
       
順列操作
畳み込み操作
数値演算
(C++23)            
未初期化ストレージに対する操作
戻り値の型
 
ヘッダー <algorithm> で定義
呼び出しシグネチャ
(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 = {} );
(C++20以降)
(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 = {} );
(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 = {} );
(C++20以降)
(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 = {} );
(C++26以降)
1) 範囲 first から last までの範囲で、value と等価なすべての要素を含むビューを返します。

範囲 [firstlast) は、value に対して少なくとも部分的に順序付けられている必要があります。つまり、以下のすべての要件を満たす必要があります。

  • element < value または comp(element, value) である要素は、その式が true となるすべての要素の前に配置される必要があります(つまり、式が false となるすべての要素の前に配置される必要があります)。
  • !(value < element) または !comp(value, element) に対してパーティショニングされている必要があります。
  • すべての要素について、element < value または comp(element, value)true の場合、!(value < element) または !comp(value, element)true である必要があります。

完全にソートされた範囲はこれらの基準を満たします。

返されるビューは2つのイテレータから構成されます。1つは value に対して「less ではない」最初の要素を指し、もう1つは value より「大きい」最初の要素を指します。最初のイテレータは std::ranges::lower_bound() で、2番目のイテレータは std::ranges::upper_bound() で取得することもできます。

2) (1) と同じですが、ソース範囲として r を使用します。これは、範囲 ranges::begin(r)first として、ranges::end(r)last として使用するのと同じです。

このページで説明されている関数のようなエンティティは、アルゴリズム関数オブジェクト(非公式にはニーブロイドとして知られている)です。つまり、

目次

[編集] パラメータ

first, last - 調査する要素の範囲を定義するイテレータとセンチネルのペア
r - 検査する要素の範囲
value - 要素と比較する値
comp - 最初の引数が2番目の引数より「less」(つまり、順序が前にある)場合
proj - 要素に適用する射影

[編集] 戻り値

std::ranges::subrange。目的の範囲を定義するイテレータのペアを含みます。最初のイテレータは value に対して「less ではない」最初の要素を指し、2番目のイテレータは value より「大きい」最初の要素を指します。

value に対して「less ではない」要素が存在しない場合、最初の要素として最後のイテレータ(last または ranges::end(r) に等しいイテレータ)が返されます。同様に、「value より大きい」要素が存在しない場合、2番目の要素として最後のイテレータが返されます。

[編集] 計算量

実行される比較回数は、firstlast の距離の対数(最大 2 * log2(last - first) + O(1) 回の比較)です。ただし、random_access_iterator をモデル化しないイテレータの場合、イテレータのインクリメント回数は線形になります。

[編集] 可能な実装

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;

[編集] 注記

機能テストマクロ 規格 機能
__cpp_lib_algorithm_default_value_type 202403 (C++26) アルゴリズム (1,2) のためのリスト初期化

[編集]

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

出力

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)

[編集] 関連項目

与えられた値より小さくない最初の要素へのイテレータを返す
(アルゴリズム関数オブジェクト)[編集]
特定の値より大きい最初の要素へのイテレータを返す
(アルゴリズム関数オブジェクト)[編集]
部分的に順序付けられた範囲に要素が存在するかどうかを判断する
(アルゴリズム関数オブジェクト)[編集]
要素の範囲を2つのグループに分割する
(アルゴリズム関数オブジェクト)[編集]
2つの要素の集合が同じかどうかを判断する
(アルゴリズム関数オブジェクト)[編集]
特定のキーに一致する要素の範囲を返す
(関数テンプレート) [編集]
English 日本語 中文(简体) 中文(繁體)