std::ranges::minmax_element, std::ranges::minmax_element_result
From cppreference.com
| ヘッダー <algorithm> で定義 |
||
| 呼び出しシグネチャ |
||
| template< std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity, std::indirect_strict_weak_order<std::projected<I, Proj>> Comp = ranges::less > |
(1) | (C++20以降) |
| template< ranges::forward_range R, class Proj = std::identity, std::indirect_strict_weak_order< |
(2) | (C++20以降) |
| ヘルパー型 |
||
| template< class I > using minmax_element_result = ranges::min_max_result<I>; |
(3) | (C++20以降) |
1) 範囲
[first, last) 内の最小要素と最大要素を検索します。このページで説明されている関数のようなエンティティは、アルゴリズム関数オブジェクト(非公式にはニーブロイドとして知られている)です。つまり、
- これらのいずれかを呼び出す際に、明示的なテンプレート引数リストを指定することはできません。
- これらのいずれも実引数依存の名前探索には見えません。
- これらのいずれかが関数呼び出し演算子の左側の名前として通常の非修飾名探索によって見つかった場合、実引数依存の名前探索は抑制されます。
目次 |
[編集] パラメータ
| first, last | - | 調査する要素の範囲を定義するイテレータとセンチネルのペア |
| r | - | 検査する range |
| comp | - | 射影された要素に適用される比較 |
| proj | - | 要素に適用される投影。 |
[編集] 戻り値
最初の要素として最小要素へのイテレータ、2 番目の要素として最大要素へのイテレータを含むオブジェクト。範囲が空の場合は {first, first} を返します。最小要素に相当する要素が複数ある場合、最初に見つかった要素へのイテレータが返されます。最大要素に相当する要素が複数ある場合、最後に見つかった要素へのイテレータが返されます。
[編集] 計算量
比較演算の適用回数は最大 std::max(std::floor(1.5 * (N − 1)), 0.0) 回、投影演算の適用回数はその 2 倍です。ここで、N = ranges::distance(first, last) です。
[編集] 実装例
struct minmax_element_fn { template<std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity, std::indirect_strict_weak_order<std::projected<I, Proj>> Comp = ranges::less> constexpr ranges::minmax_element_result<I> operator()(I first, S last, Comp comp = {}, Proj proj = {}) const { auto min = first, max = first; if (first == last || ++first == last) return {min, max}; if (std::invoke(comp, std::invoke(proj, *first), std::invoke(proj, *min))) min = first; else max = first; while (++first != last) { auto i = first; if (++first == last) { if (std::invoke(comp, std::invoke(proj, *i), std::invoke(proj, *min))) min = i; else if (!(std::invoke(comp, std::invoke(proj, *i), std::invoke(proj, *max)))) max = i; break; } else { if (std::invoke(comp, std::invoke(proj, *first), std::invoke(proj, *i))) { if (std::invoke(comp, std::invoke(proj, *first), std::invoke(proj, *min))) min = first; if (!(std::invoke(comp, std::invoke(proj, *i), std::invoke(proj, *max)))) max = i; } else { if (std::invoke(comp, std::invoke(proj, *i), std::invoke(proj, *min))) min = i; if (!(std::invoke(comp, std::invoke(proj, *first), std::invoke(proj, *max)))) max = first; } } } return {min, max}; } template<ranges::forward_range R, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<ranges::iterator_t<R>, Proj>> Comp = ranges::less> constexpr ranges::minmax_element_result<ranges::borrowed_iterator_t<R>> operator()(R&& r, Comp comp = {}, Proj proj = {}) const { return (*this)(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj)); } }; inline constexpr minmax_element_fn minmax_element; |
[編集] 例
このコードを実行
#include <algorithm> #include <iostream> #include <iterator> namespace ranges = std::ranges; int main() { const auto v = {3, 9, 1, 4, 1, 2, 5, 9}; const auto [min, max] = ranges::minmax_element(v); std::cout << "min = " << *min << ", at [" << ranges::distance(v.begin(), min) << "]\n" << "max = " << *max << ", at [" << ranges::distance(v.begin(), max) << "]\n"; }
出力
min = 1, at [2] max = 9, at [7]
[編集] 関連項目
| (C++20) |
範囲内で最小の要素を返す (アルゴリズム関数オブジェクト) |
| (C++20) |
範囲内で最大の要素を返す (アルゴリズム関数オブジェクト) |
| (C++20) |
2つの要素の小さい方と大きい方を返す (アルゴリズム関数オブジェクト) |
| (C++11) |
範囲内で最小の要素と最大の要素を返す (関数テンプレート) |