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
๋ฅผ ๋ฐํํ๋ ๋ง์ง๋ง ์์๋ฅผ ๊ฒ์ํฉ๋๋ค.
์ด ํ์ด์ง์์ ์ค๋ช ํ๋ ํจ์ํ ๊ฐ์ฒด๋ค์ algorithm function objects (์ผ๋ฐ์ ์ผ๋ก niebloids ๋ก ์๋ ค์ง)์ ๋๋ค. ์ฆ:
- ๋ช ์์ ํ ํ๋ฆฟ ์ธ์ ๋ชฉ๋ก์ ์ด๋ค ์ค ์ด๋ ๊ฒ์ ํธ์ถํ ๋๋ ์ง์ ํ ์ ์์ต๋๋ค.
- ์ด๋ค ์ค ์ด๋ ๊ฒ๋ ์ธ์ ์์กด ์ด๋ฆ ๊ฒ์ ์ ๋ณด์ด์ง ์์ต๋๋ค.
- ์ด๋ค ์ค ์ด๋ ๊ฒ์ด ํจ์ ํธ์ถ ์ฐ์ฐ์์ ์ผ์ชฝ ์ด๋ฆ์ผ๋ก ์ผ๋ฐ ๋นํ์ ์ด๋ฆ ๊ฒ์ ์ ์ํด ๋ฐ๊ฒฌ๋ ๋, ์ธ์ ์์กด ์ด๋ฆ ๊ฒ์ ์ด ์ต์ ๋ฉ๋๋ค.
๋ชฉ์ฐจ |
๋งค๊ฐ๋ณ์
| first, last | - | ๊ฒ์ฌํ ์์๋ค์ ๋ฒ์ ๋ฅผ ์ ์ํ๋ ๋ฐ๋ณต์-๊ฐ์์ ์ |
| r | - | ๊ฒ์ฌํ ์์๋ค์ ๋ฒ์ |
| value | - | ์์๋ค๊ณผ ๋น๊ตํ ๊ฐ |
| pred | - | ํฌ์๋ ์์๋ค์ ์ ์ฉํ ์กฐ๊ฑด์ |
| proj | - | ์์๋ค์ ์ ์ฉํ ํฌ์ |
๋ฐํ๊ฐ
[
first
,
last
)
์์
E
๊ฐ
true
์ธ ๋ง์ง๋ง ๋ฐ๋ณต์๋ผ๊ณ ํ์.
๋ณต์ก๋
์ต๋ 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) | ๋ชฉ๋ก ์ด๊ธฐํ for algorithms ( 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๊ฐ ๋จ์ forward_iterator์ธ ๊ฒฝ์ฐ, begin๋ถํฐ end๊น์ง๋ง ์ํํ ์ ์์ต๋๋ค. 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์ธ ๊ฒฝ์ฐ, begin๋ถํฐ end๊น์ง๋ง ์ํํ ์ ์์ต๋๋ค. 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) |
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๊ฐ ๋จ์ forward_iterator์ธ ๊ฒฝ์ฐ, begin๋ถํฐ end๊น์ง๋ง ์ํํ ์ ์์ต๋๋ค. 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 { {"ํ๋", 1}, {"two", 2}, {"three", 3}, {"ํ๋", 4}, {"two", 5}, {"three", 6}, }; auto cmp_one = [](const std::string_view &s) { return s == "ํ๋"; }; // comparator๋ฅผ ๋ง์กฑํ๋ ๊ฐ์ฅ ์ต์ ์์๋ฅผ ์ฐพ๊ณ , 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(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)
|
๋ฒ์๊ฐ ์ฃผ์ด์ง ์์๋ ๋ถ๋ถ ๋ฒ์๋ฅผ ํฌํจํ๋์ง ํ์ธํจ
(์๊ณ ๋ฆฌ์ฆ ํจ์ ๊ฐ์ฒด) |