Namespaces
Variants

std::ranges::find_last, std::ranges::find_last_if, std::ranges::find_last_if_not

cppreference.net에서
 
 
알고리즘 라이브러리
제약된 알고리즘 및 ranges 기반 알고리즘 (C++20)
제약된 알고리즘, 예: ranges::copy, ranges::sort, ...
정렬 및 관련 연산
분할 연산
(C++11)    

정렬 연산
이진 탐색 연산
(분할된 범위에 대해)
집합 연산 (정렬된 범위에 대해)
병합 연산 (정렬된 범위에 대해)
힙 연산
최소/최대 연산
(C++11)
(C++17)
사전식 비교 연산
순열 연산


 
제약된 알고리즘
이 메뉴의 모든 이름은 std::ranges
네임스페이스에 속합니다
(C++23)
unique_copy
stable_partition
partial_sort_copy
equal_range
set_symmetric_difference
pop_heap
clamp
prev_permutation
fold_left
fold_left_first  
fold_right
fold_right_last  
fold_left_with_iter
fold_left_first_with_iter
(C++23)
iota            
(C++23)
generate_random
(C++26)
uninitialized_value_construct_n
 
(C++23)<algorithm>
헤더
template< std::forward_iterator I, std::sentinel_for<I> S,
          class T,
          class Proj = std::identity >
    requires std::indirect_binary_predicate
                 <ranges::equal_to, std::projected<I, Proj>, const T*>
constexpr ranges::subrange<I>
    find_last( I first, S last, const T& value, Proj proj = {} );
에 정의됨 호출 시그니처
(1)
template< std::forward_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity,
          class T = std::projected_value_t<I, Proj> >
    requires std::indirect_binary_predicate
                 <ranges::equal_to, std::projected<I, Proj>, const T*>
constexpr ranges::subrange<I>
    find_last( I first, S last, const T& value, Proj proj = {} );
(C++23부터)
template< ranges::forward_range R,
          class T,
          class Proj = std::identity >
    requires std::indirect_binary_predicate
                 <ranges::equal_to,
                  std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::borrowed_subrange_t<R>
    find_last( R&& r, const T& value, Proj proj = {} );
(C++26까지) (C++26부터)
(2)
template< ranges::forward_range R,
          class Proj = std::identity,
          class T = std::projected_value_t<ranges::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>
    find_last( R&& r, const T& value, Proj proj = {} );
(C++23부터)
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>
    find_last_if( I first, S last, Pred pred, Proj proj = {} );
(C++26까지) (C++26부터)
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>
    find_last_if( R&& r, Pred pred, Proj proj = {} );
(3) (C++23부터)
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>
    find_last_if_not( I first, S last, Pred pred, Proj proj = {} );
(4) (C++23부터)
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>
    find_last_if_not( R&& r, Pred pred, Proj proj = {} );
(5) (C++23부터)
template< /*execution-policy*/ Ep,
          std::random_access_iterator I, std::sized_sentinel_for<I> S,
          class Proj = std::identity,
          class T = std::projected_value_t<I, Proj> >
    requires std::indirect_binary_predicate
                 <ranges::equal_to, std::projected<I, Proj>, const T*>
ranges::subrange<I> find_last( Ep&& policy, I first, S last,
                               const T& value, Proj proj = {} );
(6) (C++23부터)
template< /*execution-policy*/ Ep, /*sized-random-access-range*/ R,
          class Proj = std::identity,
          class T = std::projected_value_t<ranges::iterator_t<R>, Proj> >
    requires std::indirect_binary_predicate
                 <ranges::equal_to,
                  std::projected<ranges::iterator_t<R>, Proj>, const T*>
ranges::borrowed_subrange_t<R>
    find_last( Ep&& policy, R&& r, const T& value, Proj proj = {} );
(7) (C++26부터)
template< /*execution-policy*/ Ep,
          std::random_access_iterator I, std::sized_sentinel_for<I> S,
          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
ranges::subrange<I> find_last_if( Ep&& policy, I first, S last,
                                  Pred pred, Proj proj = {} );
(8) (C++26부터)
template< /*execution-policy*/ Ep, /*sized-random-access-range*/ R,
          class Proj = std::identity,
          std::indirect_unary_predicate
              <std::projected<ranges::iterator_t<R>, Proj>> Pred >
ranges::borrowed_subrange_t<R>
    find_last_if( Ep&& policy, R&& r, Pred pred, Proj proj = {} );
(9) (C++26부터)
template< /*execution-policy*/ Ep,
          std::random_access_iterator I, std::sized_sentinel_for<I> S,
          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
ranges::subrange<I> find_last_if_not( Ep&& policy, I first, S last,
                                      Pred pred, Proj proj = {} );
(10) (C++26부터)
template< /*execution-policy*/ Ep, /*sized-random-access-range*/ R,
          class Proj = std::identity,
          std::indirect_unary_predicate
              <std::projected<ranges::iterator_t<R>, Proj>> Pred >
ranges::borrowed_subrange_t<R>
    find_last_if_not( Ep&& policy, R&& r, Pred pred, Proj proj = {} );
(11) (C++26부터)

(12) /*execution-policy*/(C++26부터)의 정의는 이 페이지/*sized-random-access-range*/를 참조하십시오; 의 정의는 이 페이지

를 참조하십시오. proj소스 범위 [first, last) 또는 r에서 특정 기준을 충족하는 (

에 의해 투영된) 마지막 요소를 반환합니다: find_last1,2)value
와(과) 같은 마지막 요소를 검색합니다. find_last_if3,4)pred 조건자 true가
을(를) 반환하는 마지막 요소를 검색합니다. find_last_if_not5,6)pred 조건자 false가
을(를) 반환하는 마지막 요소를 검색합니다.7-12) (1-6)policy과 같지만,

에 따라 실행됩니다.이 페이지에 설명된 함수형 엔티티는 알고리즘 함수 객체(비공식적으로 niebloids

매개변수

first, last - 소스 범위
를 정의하는 반복자-센티널 쌍 - 소스 범위
value - 대상 값
pred - (투영된) 요소에 적용할 조건자
proj - 요소에 적용할 투영
policy - 사용할 실행 정책

반환값

조건을 충족하는 마지막 요소부터 소스 범위의 끝까지의 부분 범위(subrange). 해당 요소가 없으면 빈 범위를 반환합니다.

복잡도

주어진 N이 ranges::distance(first, last) 또는 ranges::distance(r)인 경우:

1,2) 최대 N번의 비교 및 proj 적용.
3-6) 최대 N번의 pred 및 proj 적용.
7,8) 𝓞(N) 번의 비교 및 proj 적용.
9-12) 𝓞(N) 번의 pred 및 proj 적용.

예외

7-12) 실행 과정 중:
  • 병렬화에 필요한 임시 메모리 자원을 사용할 수 없는 경우 std::bad_alloc이 발생합니다.
  • 알고리즘 인자를 통해 객체에 접근하는 도중 처리되지 않은 예외가 발생하면, 실행 정책에 따라 동작이 결정됩니다(표준 정책의 경우 std::terminate이 호출됩니다).

참고 사항

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
struct find_last_fn
{
    template<std::forward_iterator I, std::sentinel_for<I> S,
             class Proj = std::identity,
             class T = std::projected_value_t<ranges::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
    {
        // Note: if I is mere forward_iterator, we may only go from begin to end.
        std::optional<I> found;
        for (; first != last; ++first)
            if (std::invoke(proj, *first) == value)
                found = first;
        
        if (!found)
            return {first, first};
        
        return {*found, 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)(ranges::begin(r),
                       ranges::next(ranges::begin(r), ranges::end(r)),
                       value, std::ref(proj));
    }
};

inline constexpr find_last_fn find_last;
find_last_if
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
    {
        // Note: if I is mere forward_iterator, we may only go from begin to 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, 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)(ranges::begin(r),
                       ranges::next(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
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
    {
        // Note: if I is mere forward_iterator, we may only go from begin to 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, 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)(ranges::begin(r),
                       ranges::next(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}

참고

특정 범위에서 마지막으로 나타나는 요소 시퀀스를 찾음
(알고리즘 함수 객체)
특정 기준을 만족하는 첫 번째 요소를 찾음
(알고리즘 함수 객체)
요소 범위가 처음으로 나타나는 위치를 검색함
(알고리즘 함수 객체)
한 시퀀스가 다른 시퀀스의 부분 수열인지 확인함
(알고리즘 함수 객체)
이진 탐색을 사용하여 범위에 요소가 존재하는지 확인함
(알고리즘 함수 객체)
범위에 지정된 요소 또는 부분 범위가 포함되어 있는지 검사함
(알고리즘 함수 객체)