Namespaces
Variants

std::ranges::equal_range

ja.cppreference.net より
 
 
アルゴリズムライブラリ
制約付きアルゴリズムと範囲アルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy、 ranges::sort、 ...
ソートおよび関連操作
分割操作
(C++11)    

ソート操作
二分探索操作
(分割された範囲に対する)
集合操作 (ソート済み範囲に対する)
マージ操作 (ソート済み範囲に対する)
ヒープ操作
最小値/最大値操作
(C++11)
(C++17)
辞書順比較操作
順列操作


 
制約付きアルゴリズム
このメニューのすべての名前は名前空間 std::ranges
非変更シーケンス操作
変更シーケンス操作
分割操作
ソート操作
二分探索操作 (ソート済み範囲に対する)
       
       
集合操作 (ソート済み範囲に対する)
ヒープ操作
最小値/最大値操作
       
       
順列操作
畳み込み操作
数値操作
(C++23)            
未初期化記憶域に対する操作
戻り値の型
 
ヘッダ <algorithm>
で定義
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)
(C++20 から)
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 まで)
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++26 から) (2)
(C++20 から)
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 まで)
(C++26 から)1)value 範囲 [first, last) 内の

と等価なすべての要素を含むビューを返します。[first, last)範囲 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小さくない最初の要素を指し、もう1つは よりvalue大きい最初の要素を指します。最初のイテレータは std::ranges::lower_bound() で、2番目のイテレータは std::ranges::upper_bound()

でそれぞれ取得することもできます。 2) これは (1)r と同じですが、ソース範囲として ranges::begin(r) を使用する点が異なります。これは、あたかも first を範囲 ranges::end(r) として使用し、last を

として使用するかのように動作します。このページで説明されている関数のようなエンティティは、アルゴリズム関数オブジェクト (通称 niebloids

  • ) です。つまり:
  • それらのいずれかを呼び出す際に、明示的なテンプレート引数リストを指定することはできません。それらのいずれも引数依存の名前探索
  • では可視ではありません。通常の非修飾名探索によって関数呼び出し演算子の左側の名前として見つかった場合、引数依存の名前探索は抑制されます。

パラメータ

first, last - 検査対象の要素の 範囲 を定義するイテレータ-番兵ペア
r - 検査対象の要素の範囲
value - 要素と比較する値
comp - 第1引数が第2引数より 小さい 場合(つまり順序付けにおいて前に来る場合)
proj - 要素に適用する射影

戻り値

std::ranges::subrange 望ましい範囲を定義するイテレータのペアを含む、最初の要素は value より 小さくない 最初の要素を指し、2番目の要素は value より 大きい 最初の要素を指す。

value 以上の要素が存在しない場合、最後のイテレータ( last または ranges:: end ( r ) に等しいイテレータ)が最初の要素として返されます。同様に、 value を 超える 要素が存在しない場合、最後のイテレータが2番目の要素として返されます。

計算量

比較回数は、 first と last の間の距離に対して対数的です(最大 2 * log 2 (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 {};
    // 注: これらの比較演算子ではnameは無視される
    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()
{
    // 注: 順序付けされておらず、以下の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);
}

出力:

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つの要素集合が同一か判定する
(アルゴリズム関数オブジェクト)
二分探索により指定された値に一致する要素の範囲を検出する
(関数テンプレート)