Namespaces
Variants

std:: transform_reduce

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
헤더 파일에 정의됨 <numeric>
template < class InputIt1, class InputIt2, class T >

T transform_reduce ( InputIt1 first1, InputIt1 last1,

InputIt2 first2, T init ) ;
(1) (C++17부터)
(C++20부터 constexpr)
template < class ExecutionPolicy,

class ForwardIt1, class ForwardIt2, class T >
T transform_reduce ( ExecutionPolicy && policy,
ForwardIt1 first1, ForwardIt1 last1,

ForwardIt2 first2, T init ) ;
(2) (C++17부터)
template < class InputIt1, class InputIt2, class T,

class BinaryOp1, class BinaryOp2 >
T transform_reduce ( InputIt1 first1, InputIt1 last1,
InputIt2 first2, T init,

BinaryOp1 reduce, BinaryOp2 transform ) ;
(3) (C++17부터)
(C++20부터 constexpr)
template < class ExecutionPolicy,

class ForwardIt1, class ForwardIt2, class T,
class BinaryOp1, class BinaryOp2 >
T transform_reduce ( ExecutionPolicy && policy,
ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 first2, T init,

BinaryOp1 reduce, BinaryOp2 transform ) ;
(4) (C++17부터)
template < class InputIt, class T,

class BinaryOp, class UnaryOp >
T transform_reduce ( InputIt first, InputIt last, T init,

BinaryOp reduce, UnaryOp transform ) ;
(5) (C++17부터)
(C++20부터 constexpr)
template < class ExecutionPolicy,

class ForwardIt, class T,
class BinaryOp, class UnaryOp >
T transform_reduce ( ExecutionPolicy && policy,
ForwardIt first, ForwardIt last, T init,

BinaryOp reduce, UnaryOp transform ) ;
(6) (C++17부터)
1) transform_reduce ( first1, last1, first2, init,
std:: plus <> ( ) , std:: multiplies <> ( ) )
와 동등하며, 기본 std::inner_product 의 효과적인 병렬화 버전입니다.
3) [ first1 , last1 ) 범위와 first2 에서 시작하는 std:: distance ( first1, last1 ) 개 요소들의 범위에 대해 각 요소 쌍에 transform 을 적용하고, 그 결과들을 (지정되지 않은 방식으로 순열 및 집계될 수 있음) 초기값 init 과 함께 reduce 를 통해 축소합니다.
결과는 reduce 가 결합 법칙이나 교환 법칙을 만족하지 않는 경우(예: 부동 소수점 덧셈) 비결정적입니다.
다음 값들 중 어느 하나라도 T 로 변환할 수 없는 경우 프로그램의 형식이 올바르지 않습니다:
  • reduce ( init, init )
  • reduce ( init, transform ( * first1, * first2 ) )
  • reduce ( transform ( * first1, * first2 ) , init )
  • reduce ( transform ( * first1, * first2 ) , transform ( * first1, * first2 ) )
주어진 last2 std:: distance ( first1, last1 ) 번째 다음 반복자인 first2 에 대해, 다음 조건 중 하나라도 만족되면 동작은 정의되지 않음:
  • T MoveConstructible 가 아닌 경우.
  • transform 또는 reduce [ first1 , last1 ) 또는 [ first2 , last2 ) 의 어떤 요소를 수정하는 경우.
  • transform 또는 reduce [ first1 , last1 ] 또는 [ first2 , last2 ] 의 어떤 반복자나 부분 범위를 무효화하는 경우.
5) 범위 [ first , last ) 내의 각 요소에 transform 을 적용하고, 초기값 init 과 함께 결과들을 (지정되지 않은 방식으로 순열 및 집계될 수 있음) reduce 를 통해 축소합니다.
결과는 reduce 가 결합 법칙이나 교환 법칙을 만족하지 않는 경우(예: 부동 소수점 덧셈) 비결정적입니다.
다음 값들 중 어느 하나라도 T 로 변환할 수 없는 경우 프로그램의 형식이 잘못되었습니다:
  • reduce ( init, init )
  • reduce ( init, transform ( * first ) )
  • reduce ( transform ( * first ) , init )
  • reduce ( transform ( * first ) , transform ( * first ) )
다음 조건 중 하나라도 만족되면, 동작은 정의되지 않음:
  • T MoveConstructible 가 아닌 경우.
  • transform 또는 reduce [ first , last ) 의 어떤 요소도 수정하는 경우.
  • transform 또는 reduce [ first , last ] 의 어떤 반복자나 부분 범위를 무효화하는 경우.
2,4,6) (1,3,5) 와 동일하지만, policy 에 따라 실행됩니다.
다음 모든 조건이 만족될 때만 이 오버로드들이 오버로드 해결에 참여합니다:

std:: is_execution_policy_v < std:: decay_t < ExecutionPolicy >> true 입니다.

(C++20 이전)

std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> true 입니다.

(C++20 이후)

목차

매개변수

first1, last1 - 범위 를 정의하는 반복자 쌍으로, transform 의 좌측 피연산자로 사용될 요소들을 지정합니다.
first2 - transform 의 우측 피연산자로 사용될 요소들의 범위 시작점입니다.
first, last - 범위 를 정의하는 반복자 쌍으로, transform 의 피연산자로 사용될 요소들을 지정합니다.
init - 일반화된 합계의 초기값입니다.
policy - 사용할 실행 정책 입니다.
reduce - 이항 FunctionObject 로, transform 의 결과, 다른 reduce 의 결과, 그리고 init 에 대해 지정되지 않은 순서로 적용됩니다.
transform - 단항 또는 이항 FunctionObject 로, 입력 범위(들)의 각 요소에 적용됩니다. 반환 타입은 reduce 의 입력으로 사용 가능해야 합니다.
타입 요구사항
-
InputIt1, InputIt2, InputIt LegacyInputIterator 요구사항을 충족해야 합니다.
-
ForwardIt1, ForwardIt2, ForwardIt LegacyForwardIterator 요구사항을 충족해야 합니다.

반환값

1,2) init values 의 일반화된 합을 std:: plus <> ( ) 에 대해 계산하며, 여기서 values std:: multiplies <> ( ) 로 변환된 값들이고, 각 값은 두 입력 범위의 요소 쌍으로부터 변환됩니다.
3,4) init values 의 일반화된 합을 reduce 를 통해 계산하며, 여기서 values transform 으로 변환된 값들이고, 각 값은 두 입력 범위의 요소 쌍으로부터 변환됩니다.
5,6) init values 의 일반화된 합을 reduce 에 대해 계산하며, 여기서 values transform 에 의해 변환된 값들이고, 각 값은 입력 범위의 요소로부터 변환됩니다.

요소 그룹의 일반화된 합 은 이진 연산 binary_op 에 대해 다음과 같이 정의됩니다:

  • 그룹에 요소가 하나만 있는 경우, 합계는 해당 요소의 값입니다.
  • 그렇지 않은 경우, 다음 작업을 순서대로 수행합니다:
  1. 그룹에서 임의의 두 요소 elem1 elem2 를 가져옵니다.
  2. binary_op ( elem1, elem2 ) 을 계산하고 결과를 그룹에 다시 넣습니다.
  3. 그룹에 요소가 하나만 남을 때까지 1단계와 2단계를 반복합니다.

복잡도

주어진 N std:: distance ( first1, last1 ) (또는 오버로드 (5,6) 의 경우 std:: distance ( first, last ) )으로 정의합니다:

1,2) O(N) 번의 std:: plus <> ( ) std:: multiplies <> ( ) 적용 각각.
3-6) O(N) 번의 reduce transform 적용 각각.

예외

ExecutionPolicy 라는 템플릿 매개변수를 사용하는 오버로드는 다음과 같이 오류를 보고합니다:

  • 알고리즘의 일부로 호출된 함수 실행 중 예외가 발생하고 ExecutionPolicy 표준 정책 중 하나인 경우, std::terminate 가 호출됩니다. 다른 ExecutionPolicy 의 경우 동작은 구현에 따라 정의됩니다.
  • 알고리즘이 메모리 할당에 실패하는 경우, std::bad_alloc 이 throw됩니다.

참고 사항

transform init 에 적용되지 않습니다.

만약 first == last 이거나 first1 == last1 인 경우, init 이 수정되지 않은 상태로 반환됩니다.

예제

transform_reduce std::inner_product 의 병렬화에 사용될 수 있습니다. 일부 시스템에서는 병렬 실행의 이점을 얻기 위해 추가 지원이 필요할 수 있습니다. 예를 들어, GNU/Linux에서는 Intel TBB 가 설치되고 gcc/clang 컴파일러에 - ltbb 옵션이 제공되어야 합니다.

#if PARALLEL
#include <execution>
#define PAR std::execution::par,
#else
#define PAR
#endif
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <locale>
#include <numeric>
#include <vector>
// to parallelize non-associate accumulative operation, you'd better choose
// transform_reduce instead of reduce; e.g., a + b * b != b + a * a
void print_sum_squared(long const num)
{
    std::cout.imbue(std::locale{"en_US.UTF8"});
    std::cout << "num = " << num << '\n';
    // create an immutable vector filled with pattern: 1,2,3,4, 1,2,3,4 ...
    const std::vector<long> v{[n = num * 4] {
        std::vector<long> v;
        v.reserve(n);
        std::generate_n(std::back_inserter(v), n,
            [i = 0]() mutable { return 1 + i++ % 4; });
        return v;
    }()};
    auto squared_sum = [](auto sum, auto val) { return sum + val * val; };
    auto sum1 = std::accumulate(v.cbegin(), v.cend(), 0L, squared_sum);
    std::cout << "accumulate(): " << sum1 << '\n';
    auto sum2 = std::reduce(PAR v.cbegin(), v.cend(), 0L, squared_sum);
    std::cout << "reduce(): " << sum2 << '\n';
    auto sum3 = std::transform_reduce(PAR v.cbegin(), v.cend(), 0L, std::plus{},
                                      [](auto val) { return val * val; });
    std::cout << "transform_reduce(): " << sum3 << "\n\n";
}
int main()
{
    print_sum_squared(1);
    print_sum_squared(1'000);
    print_sum_squared(1'000'000);
}

가능한 출력:

num = 1
accumulate(): 30
reduce(): 30
transform_reduce(): 30
num = 1,000
accumulate(): 30,000
reduce(): -7,025,681,278,312,630,348
transform_reduce(): 30,000
num = 1,000,000
accumulate(): 30,000,000
reduce(): -5,314,886,882,370,003,032
transform_reduce(): 30,000,000
// Compile-options for parallel execution on POSIX:
// g++ -O2 -std=c++17 -Wall -Wextra -pedantic -DPARALLEL ./example.cpp -ltbb -o tr; ./tr

참고 항목

요소 범위의 합계를 계산하거나 접습니다
(function template)
요소 범위에 함수를 적용하여 결과를 대상 범위에 저장합니다
(function template)
(C++17)
std::accumulate 와 유사하지만 순서가 보장되지 않습니다
(function template)