Namespaces
Variants

std::ranges::fold_left_first_with_iter, std::ranges::fold_left_first_with_iter_result

cppreference.net에서
 
 
알고리즘 라이브러리
제약된 알고리즘 및 범위 기반 알고리즘 (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::input_iterator I, std::sentinel_for<I> S,
          /*indirectly-binary-left-foldable*/<std::iter_value_t<I>, I> F >
requires std::constructible_from<
             std::iter_value_t<I>, std::iter_reference_t<I>>
constexpr /* see description */
    fold_left_first_with_iter( I first, S last, F f );
에 정의됨 호출 시그니처
template< ranges::input_range R,
          /*indirectly-binary-left-foldable*/<
              ranges::range_value_t<R>, ranges::iterator_t<R>> F >
requires std::constructible_from<
             ranges::range_value_t<R>, ranges::range_reference_t<R>>
constexpr /* see description */
    fold_left_first_with_iter( R&& r, F f );
(1) (C++23부터)
(2)
template< class F, class T, class I >
concept /*indirectly-binary-left-foldable*/ = /* see description */;
(C++23부터) 헬퍼 개념 (3) (
설명 전용*
template< class I, class T >
using fold_left_first_with_iter_result = ranges::in_value_result<I, T>;
) 헬퍼 클래스 템플릿

(4) (C++23부터)주어진 범위의 요소를 왼쪽-폴드합니다. 즉, 체인 표현식
f(f(f(f(x1, x2), x3), ...), xn)의 평가 결과를 반환합니다. 여기서 x1, x2, ..., xn는 범위의 요소입니다.

비공식적으로, ranges::fold_left_first_with_iter는 이진 술어를 받는 std::accumulate의 오버로드와 유사하게 동작하지만, *first이 내부적으로 초기 요소로 사용된다는 점이 다릅니다.

[first, last)이 유효한 범위가 아닌 경우 동작은 정의되지 않습니다.

1) 범위는 [first, last)입니다.
2) (1)과 동일하지만, r을 범위로 사용합니다. 이는 ranges::begin(r)을 first으로, ranges::end(r)을 last으로 사용하는 것과 같습니다.
3) 다음과 동일:
헬퍼 개념
template< class F, class T, class I, class U >
concept /*indirectly-binary-left-foldable-impl*/ =
    std::movable<T> &&
    std::movable<U> &&
    std::convertible_to<T, U> &&
    std::invocable<F&, U, std::iter_reference_t<I>> &&
    std::assignable_from<U&,
        std::invoke_result_t<F&, U, std::iter_reference_t<I>>>;
(3A) (설명 전용*)
template< class F, class T, class I >
concept /*indirectly-binary-left-foldable*/ =
    std::copy_constructible<F> &&
    std::indirectly_readable<I> &&
    std::invocable<F&, T, std::iter_reference_t<I>> &&
    std::convertible_to<std::invoke_result_t<F&, T, std::iter_reference_t<I>>,
        std::decay_t<std::invoke_result_t<F&, T, std::iter_reference_t<I>>>> &&
    /*indirectly-binary-left-foldable-impl*/<F, T, I,
        std::decay_t<std::invoke_result_t<F&, T, std::iter_reference_t<I>>>>;
(3B) (설명 전용*)
4) 반환 타입 별칭. 자세한 내용은 "반환값" 섹션을 참조하십시오.

이 페이지에 설명된 함수 유형 엔티티는 알고리즘 함수 객체입니다(비공식적으로 niebloids라고도 함). 즉:

매개변수

first, last - 접기할 요소들의 범위 를 정의하는 반복자-감시자 쌍
r - 접기할 요소들의 범위
f - 이항 함수 객체

반환값

U 를 decltype ( ranges:: fold_left ( std :: move ( first ) , last, std:: iter_value_t < I > ( * first ) , f ) ) 라고 하자.

1) ranges :: fold_left_first_with_iter_result < I, std:: optional < U >> 타입의 객체.
  • 멤버 ranges :: in_value_result :: in 는 범위의 끝을 가리키는 반복자를 보유합니다.
  • 멤버 ranges :: in_value_result :: value 는 주어진 범위에 대한 f 를 통한 왼쪽- 폴드 의 결과를 보유합니다.
범위가 비어 있는 경우, 반환 값은 { std :: move ( first ) , std:: optional < U > ( ) } 입니다.
2) (1) 과 동일하지만 반환 타입이 ranges :: fold_left_first_with_iter_result < ranges:: borrowed_iterator_t < R > , std:: optional < U >> 입니다.

가능한 구현

class fold_left_first_with_iter_fn
{
    template<class O, class I, class S, class F>
    constexpr auto impl(I&& first, S&& last, F f) const
    {
        using U = decltype(
            ranges::fold_left(std::move(first), last, std::iter_value_t<I>(*first), f)
        );
        using Ret = ranges::fold_left_first_with_iter_result<O, std::optional<U>>;
        if (first == last)
            return Ret{std::move(first), std::optional<U>()};
        std::optional<U> init(std::in_place, *first);
        for (++first; first != last; ++first)
            *init = std::invoke(f, std::move(*init), *first);
        return Ret{std::move(first), std::move(init)};
    }
public:
    template<std::input_iterator I, std::sentinel_for<I> S,
             /*indirectly-binary-left-foldable*/<std::iter_value_t<I>, I> F>
    requires std::constructible_from<std::iter_value_t<I>, std::iter_reference_t<I>>
    constexpr auto operator()(I first, S last, F f) const
    {
        return impl<I>(std::move(first), std::move(last), std::ref(f));
    }
    template<ranges::input_range R, /*indirectly-binary-left-foldable*/<
        ranges::range_value_t<R>, ranges::iterator_t<R>> F>
    requires
        std::constructible_from<ranges::range_value_t<R>, ranges::range_reference_t<R>>
    constexpr auto operator()(R&& r, F f) const
    {
        return impl<ranges::borrowed_iterator_t<R>>(
            ranges::begin(r), ranges::end(r), std::ref(f)
        );
    }
};
inline constexpr fold_left_first_with_iter_fn fold_left_first_with_iter;

복잡도

정확히 ranges:: distance ( first, last ) - 1 (범위가 비어 있지 않다고 가정할 때)번 함수 객체 f 가 적용됩니다.

참고 사항

다음 표는 모든 제약 조건을 가진 폴딩 알고리즘들을 비교한 것입니다:

폴드 함수 템플릿 시작 방향 초기값 반환 타입
ranges:: fold_left 왼쪽 init U
ranges:: fold_left_first 왼쪽 첫 번째 요소 std:: optional < U >
ranges:: fold_right 오른쪽 init U
ranges:: fold_right_last 오른쪽 마지막 요소 std:: optional < U >
ranges:: fold_left_with_iter 왼쪽 init

(1) ranges:: in_value_result < I, U >

(2) ranges:: in_value_result < BR, U > ,

여기서 BR 은 ranges:: borrowed_iterator_t < R >

ranges :: fold_left_first_with_iter 왼쪽 첫 번째 요소

(1) ranges:: in_value_result < I, std:: optional < U >>

(2) ranges:: in_value_result < BR, std:: optional < U >>

여기서 BR 은 ranges:: borrowed_iterator_t < R >

기능 테스트 매크로 값 표준 기능
__cpp_lib_ranges_fold 202207L (C++23) std::ranges 폴드 알고리즘

예제

#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <ranges>
#include <utility>
#include <vector>
int main()
{
    std::vector v{1, 2, 3, 4, 5, 6, 7, 8};
    auto sum = std::ranges::fold_left_first_with_iter
    (
        v.begin(), v.end(), std::plus<int>()
    );
    std::cout << "sum: " << sum.value.value() << '\n';
    assert(sum.in == v.end());
    auto mul = std::ranges::fold_left_first_with_iter(v, std::multiplies<int>());
    std::cout << "mul: " << mul.value.value() << '\n';
    assert(mul.in == v.end());
    // 벡터 내 모든 pair의 second 값의 곱을 구함:
    std::vector<std::pair<char, float>> data {{'A', 2.f}, {'B', 3.f}, {'C', 7.f}};
    auto sec = std::ranges::fold_left_first_with_iter
    (
        data | std::ranges::views::values, std::multiplies<>()
    );
    std::cout << "sec: " << sec.value.value() << '\n';
    // 프로그램 정의 함수 객체(람다 표현식) 사용:
    auto lambda = [](int x, int y) { return x + y + 2; };
    auto val = std::ranges::fold_left_first_with_iter(v, lambda);
    std::cout << "val: " << val.value.value() << '\n';
    assert(val.in == v.end());
}

출력:

sum: 36
mul: 40320
sec: 42
val: 50

참고문헌

  • C++23 표준 (ISO/IEC 14882:2024):
  • 27.6.18 Fold [alg.fold]

참고 항목

요소 범위를 왼쪽으로 폴딩
(알고리즘 함수 객체)
첫 번째 요소를 초기값으로 사용하여 요소 범위를 왼쪽으로 폴딩
(알고리즘 함수 객체)
요소 범위를 오른쪽으로 폴딩
(알고리즘 함수 객체)
마지막 요소를 초기값으로 사용하여 요소 범위를 오른쪽으로 폴딩
(알고리즘 함수 객체)
요소 범위를 왼쪽으로 폴딩하고 pair (반복자, 값)을 반환
(알고리즘 함수 객체)
요소 범위를 합산하거나 폴딩
(함수 템플릿)
(C++17)
std::accumulate 와 유사하지만 순서가 보장되지 않음
(함수 템플릿)