std::ranges:: find_last, std::ranges:: find_last_if, std::ranges:: find_last_if_not
|
定義済みヘッダー
<algorithm>
|
||
|
呼び出しシグネチャ
|
||
| (1) | ||
|
template
<
std::
forward_iterator
I,
std::
sentinel_for
<
I
>
S,
class
T,
|
(C++23以降)
(C++26まで) |
|
|
template
<
std::
forward_iterator
I,
std::
sentinel_for
<
I
>
S,
class
Proj
=
std::
identity
,
|
(C++26以降) | |
| (2) | ||
|
template
<
ranges::
forward_range
R,
class
T,
|
(C++23以降)
(C++26まで) |
|
|
template
<
ranges::
forward_range
R,
class
Proj
=
std::
identity
,
|
(C++26以降) | |
|
template
<
std::
forward_iterator
I,
std::
sentinel_for
<
I
>
S,
class
Proj
=
std::
identity
,
|
(3) | (C++23以降) |
|
template
<
ranges::
forward_range
R,
class
Proj
=
std::
identity
,
|
(4) | (C++23以降) |
|
template
<
std::
forward_iterator
I,
std::
sentinel_for
<
I
>
S,
class
Proj
=
std::
identity
,
|
(5) | (C++23以降) |
|
template
<
ranges::
forward_range
R,
class
Proj
=
std::
identity
,
|
(6) | (C++23以降) |
範囲
[
first
,
last
)
内で特定の条件を満たす最後の要素を返します:
find_last
は
value
と等しい要素を検索します。
find_last_if
は範囲
[
first
,
last
)
内で述語
pred
が
true
を返す最後の要素を検索します。
find_last_if_not
は範囲
[
first
,
last
)
内で述語
pred
が
false
を返す最後の要素を検索します。
このページで説明されている関数ライクな実体は、 アルゴリズム関数オブジェクト (非公式には niebloids として知られる)です。すなわち:
- 明示的なテンプレート引数リストは、いずれかを呼び出す際に指定することはできません。
- いずれも 実引数依存の名前探索 では可視になりません。
- いずれかが関数呼び出し演算子の左側の名前として 通常の非修飾名前探索 によって見つかった場合、 実引数依存の名前探索 は抑制されます。
目次 |
パラメータ
| first, last | - | 検査対象の要素の 範囲 を定義するイテレータ-センチネルペア |
| r | - | 検査対象の要素の範囲 |
| value | - | 要素と比較する値 |
| pred | - | 投影された要素に適用する述語 |
| proj | - | 要素に適用する投影 |
戻り値
[
first
,
last
)
内で
E
が
true
となる最後のイテレータを
i
とする。
ranges::subrange<I>{i, last}
を返す。
そのようなイテレータが見つからない場合は
ranges::subrange<I>{last, last}
を返す。
計算量
最大で last - first 回の述語と射影の適用。
注記
ranges::find_last
,
ranges::find_last_if
,
ranges::find_last_if_not
は、
I
が
bidirectional_iterator
または(さらに良い場合)
random_access_iterator
をモデル化する場合、一般的な実装においてより優れた効率性を持ちます。
| 機能テスト マクロ | 値 | 標準 | 機能 |
|---|---|---|---|
__cpp_lib_ranges_find_last
|
202207L
|
(C++23) |
ranges::find_last
,
ranges::find_last_if
,
ranges::find_last_if_not
|
__cpp_lib_algorithm_default_value_type
|
202403L
|
(C++26) | リスト初期化 アルゴリズム用 ( 1,2 ) |
実装例
これらの実装は、
I
が
forward_iterator
をモデル化する場合に使用される低速なアルゴリズムのみを示しています。
| find_last (1,2) |
|---|
struct find_last_fn { template<std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity, class T = std::projected_value_t<iterator_t<R>, Proj>> requires std::indirect_binary_predicate <ranges::equal_to, std::projected<I, Proj>, const T*> constexpr ranges::subrange<I> operator()(I first, S last, const T &value, Proj proj = {}) const { // 注: Iが単なる前方イテレータの場合、先頭から末尾までしか走査できない std::optional<I> found; for (; first != last; ++first) if (std::invoke(proj, *first) == value) found = first; if (!found) return {first, first}; return {*found, std::ranges::next(*found, last)}; } template<ranges::forward_range R, class Proj = std::identity, class T = std::projected_value_t<iterator_t<R>, Proj>> requires std::indirect_binary_predicate <ranges::equal_to, std::projected<ranges::iterator_t<R>, Proj>, const T*> constexpr ranges::borrowed_subrange_t<R> operator()(R&& r, const T &value, Proj proj = {}) const { return this->operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj)); } }; inline constexpr find_last_fn find_last; |
| find_last_if (3,4) |
struct find_last_if_fn { template<std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity, std::indirect_unary_predicate<std::projected<I, Proj>> Pred> constexpr ranges::subrange<I> operator()(I first, S last, Pred pred, Proj proj = {}) const { // 注: Iが単なるforward_iteratorの場合、先頭から末尾までしか走査できない std::optional<I> found; for (; first != last; ++first) if (std::invoke(pred, std::invoke(proj, *first))) found = first; if (!found) return {first, first}; return {*found, std::ranges::next(*found, last)}; } template<ranges::forward_range R, class Proj = std::identity, std::indirect_unary_predicate <std::projected<ranges::iterator_t<R>, Proj>> Pred> constexpr ranges::borrowed_subrange_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const { return this->operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); } }; inline constexpr find_last_if_fn find_last_if; |
| find_last_if_not (5,6) |
| find_last_if_not (5,6) |
struct find_last_if_not_fn { template<std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity, std::indirect_unary_predicate<std::projected<I, Proj>> Pred> constexpr ranges::subrange<I> operator()(I first, S last, Pred pred, Proj proj = {}) const { // 注: Iが単なる前方イテレータの場合、先頭から末尾までしか走査できない std::optional<I> found; for (; first != last; ++first) if (!std::invoke(pred, std::invoke(proj, *first))) found = first; if (!found) return {first, first}; return {*found, std::ranges::next(*found, last)}; } template<ranges::forward_range R, class Proj = std::identity, std::indirect_unary_predicate <std::projected<ranges::iterator_t<R>, Proj>> Pred> constexpr ranges::borrowed_subrange_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const { return this->operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); } }; inline constexpr find_last_if_not_fn find_last_if_not; |
例
#include <algorithm> #include <cassert> #include <forward_list> #include <iomanip> #include <iostream> #include <string_view> int main() { namespace ranges = std::ranges; constexpr static auto v = {1, 2, 3, 1, 2, 3, 1, 2}; { constexpr auto i1 = ranges::find_last(v.begin(), v.end(), 3); constexpr auto i2 = ranges::find_last(v, 3); static_assert(ranges::distance(v.begin(), i1.begin()) == 5); static_assert(ranges::distance(v.begin(), i2.begin()) == 5); } { constexpr auto i1 = ranges::find_last(v.begin(), v.end(), -3); constexpr auto i2 = ranges::find_last(v, -3); static_assert(i1.begin() == v.end()); static_assert(i2.begin() == v.end()); } auto abs = [](int x) { return x < 0 ? -x : x; }; { auto pred = [](int x) { return x == 3; }; constexpr auto i1 = ranges::find_last_if(v.begin(), v.end(), pred, abs); constexpr auto i2 = ranges::find_last_if(v, pred, abs); static_assert(ranges::distance(v.begin(), i1.begin()) == 5); static_assert(ranges::distance(v.begin(), i2.begin()) == 5); } { auto pred = [](int x) { return x == -3; }; constexpr auto i1 = ranges::find_last_if(v.begin(), v.end(), pred, abs); constexpr auto i2 = ranges::find_last_if(v, pred, abs); static_assert(i1.begin() == v.end()); static_assert(i2.begin() == v.end()); } { auto pred = [](int x) { return x == 1 or x == 2; }; constexpr auto i1 = ranges::find_last_if_not(v.begin(), v.end(), pred, abs); constexpr auto i2 = ranges::find_last_if_not(v, pred, abs); static_assert(ranges::distance(v.begin(), i1.begin()) == 5); static_assert(ranges::distance(v.begin(), i2.begin()) == 5); } { auto pred = [](int x) { return x == 1 or x == 2 or x == 3; }; constexpr auto i1 = ranges::find_last_if_not(v.begin(), v.end(), pred, abs); constexpr auto i2 = ranges::find_last_if_not(v, pred, abs); static_assert(i1.begin() == v.end()); static_assert(i2.begin() == v.end()); } using P = std::pair<std::string_view, int>; std::forward_list<P> list { {"one", 1}, {"two", 2}, {"three", 3}, {"one", 4}, {"two", 5}, {"three", 6}, }; auto cmp_one = [](const std::string_view &s) { return s == "one"; }; // コンパレータを満たす最新の要素を見つけ、pair::firstを射影する const auto subrange = ranges::find_last_if(list, cmp_one, &P::first); std::cout << "見つかった要素とそれ以降の末尾部分は:\n"; for (P const& e : subrange) std::cout << '{' << std::quoted (注:指示に従い、HTMLタグ・属性は翻訳せず、C++固有用語も翻訳していません。表示されるテキスト「std::quoted」はC++標準ライブラリの関数名であるため、そのまま保持しています)(e.first) << ", " << e.second << "} "; std::cout << '\n'; #if __cpp_lib_algorithm_default_value_type const auto i3 = ranges::find_last(list, {"three", 3}); // (2) C++26 #else const auto i3 = ranges::find_last(list, P{"three", 3}); // (2) C++23 #endif assert(i3.begin()->first == "three" && i3.begin()->second == 3); }
出力:
見つかった要素とそれ以降の末尾は:
{"one", 4} {"two", 5} {"three", 6}
関連項目
|
(C++20)
|
特定の範囲内で要素の最後のシーケンスを見つける
(アルゴリズム関数オブジェクト) |
|
(C++20)
(C++20)
(C++20)
|
特定の条件を満たす最初の要素を見つける
(アルゴリズム関数オブジェクト) |
|
(C++20)
|
要素の範囲の最初の出現を検索する
(アルゴリズム関数オブジェクト) |
|
(C++20)
|
一方のシーケンスが他方の部分シーケンスである場合に
true
を返す
(アルゴリズム関数オブジェクト) |
|
(C++20)
|
要素が半順序範囲内に存在するかどうかを判定する
(アルゴリズム関数オブジェクト) |
|
(C++23)
(C++23)
|
範囲が指定された要素または部分範囲を含むかどうかをチェックする
(アルゴリズム関数オブジェクト) |