C++ 参考手册

位置:首页 > C++ 参考手册 >算法库 > std::transform_reduce

定义于头文件 <numeric>
(1)
template<class InputIt1, class InputIt2, class T>
T transform_reduce(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init);
(C++17 起)
(C++20 前)
template<class InputIt1, class InputIt2, class T>
constexpr T transform_reduce(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init);
(C++20 起)
(2)
template <class InputIt1, class InputIt2, class T, class BinaryOp1, class BinaryOp2>

T transform_reduce(InputIt1 first1, InputIt1 last1, InputIt2 first2,

                   T init, BinaryOp1 binary_op1, BinaryOp2 binary_op2);
(C++17 起)
(C++20 前)
template <class InputIt1, class InputIt2, class T, class BinaryOp1, class BinaryOp2>

constexpr T transform_reduce(InputIt1 first1, InputIt1 last1, InputIt2 first2,

                             T init, BinaryOp1 binary_op1, BinaryOp2 binary_op2);
(C++20 起)
(3)
template<class InputIt, class T, class BinaryOp, class UnaryOp>

T transform_reduce(InputIt first, InputIt last,

                   T init, BinaryOp binop, UnaryOp unary_op);
(C++17 起)
(C++20 前)
template<class InputIt, class T, class BinaryOp, class UnaryOp>

constexpr T transform_reduce(InputIt first, InputIt last,

                             T init, BinaryOp binop, UnaryOp unary_op);
(C++20 起)
template<class ExecutionPolicy,

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

                   ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, T init);
(4) (C++17 起)
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 binary_op1, BinaryOp2 binary_op2);
(5) (C++17 起)
template<class ExecutionPolicy,

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

                   T init, BinaryOp binary_op, UnaryOp unary_op);
(6) (C++17 起)
1) 等价于 transform_reduce(first1, last1, first2, init, std::plus<>(), std::multiplies<>()); ,默认的 std::inner_product 的等效并行版本
2) 应用 binary_op2 到来自范围 [first; last) 和始于 first2 的范围的每对元素,并在 binary_op1 上与初始值 init 一同规约结果(可以以未指定行为重排聚合)
3) 应用 unary_op 到范围 [first; last) 中的每个元素,并在 binary_op 上与初始值 init 一同规约结果(可以以未指定行为重排聚合)。
4-6)(1-3) ,但按照 policy 执行。此重载仅若 std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> 为 true才参与重载决议

binary_op/binary_op2 为非交换或非结合则行为不确定。

unary_opbinary_opbinary_op1binary_op2 修改输入范围中的任何元素或非法化范围中的任何迭代器,含尾迭代器,则行为未定义。

参数

first, last - 要应用算法的元素范围
init - 广义和的初始值
policy - 使用的执行策略,细节见执行策略
unary_op - 将应用于输入范围的每个元素的一元函数对象 (FunctionObject) 。返回类型必须可为 binary_op 的输入所接受
binary_op - 将以未指定顺序应用于 unary_op 的结果、其他 binary_op 的结果和 init 的二元函数对象 (FunctionObject)
类型要求
-
为使用重载 (3,6) , T 必须满足可移动构造 (MoveConstructible) 的要求。且表达式 binary_op(init, unary_op(*first))binary_op(unary_op(*first), init)binary_op(init, init)binary_op(unary_op(*first), unary_op(*first)) 的结果必须可转换为 T
-
为使用重载 (2,5) , T 必须满足可移动构造 (MoveConstructible) 的要求。且表达式 binary_op1(init, binary_op2(*first1, *first2))binary_op1(binary_op2(*first1, *first2), init)binary_op1(init, init)binary_op1(binary_op2(*first1, *first2), binary_op2(*first1, *first2)) 的结果必须可转换为 T
-
InputIt 必须满足遗留输入迭代器 (LegacyInputIterator) 的要求。
-
ForwardIt 必须满足遗留向前迭代器 (LegacyForwardIterator) 的要求。

返回值

2) initbinary_op2(*first,*first2)binary_op2(*(first+1),*(first2+1)) ……在 binary_op1 上的广义和
3) initunary_op(*first)unary_op(*(first+1)) …… unary_op(*(last-1))binary_op 上的广义和,

其中广义和 GSUM(op, a
1
, ..., a
N
)
定义如下:

  • N=1 ,则为 a
    1
  • N > 1 ,则为 op(GSUM(op, b
    1
    , ..., b
    K
    ), GSUM(op, b
    M
    , ..., b
    N
    ))
    ,其中
  • b
    1
    , ..., b
    N
    可以是 a1, ..., aN 的任意重排,若
  • 1 < K+1 = M ≤ N

换言之, unary_op 或 binary_op1 的结果能以任意顺序组合排列。

复杂度

1,2,4,5) 各使用 O(last1 - first1)binary_op1binary_op2
3,6) 各使用 O(last - first)unary_opbinary_op

异常

拥有名为 ExecutionPolicy 的模板形参的重载按下列方式报告错误:

  • 若作为算法一部分调用的函数的执行抛出异常,且 ExecutionPolicy标准策略之一,则调用 std::terminate 。对于任何其他 ExecutionPolicy ,行为是实现定义的。
  • 若算法无法分配内存,则抛出 std::bad_alloc

注解

在一元-二元重载 (3,6) 中, unary_op 不应用到 init

first == lastfirst1 == last1 ,则返回不修改的 init

示例

transform_reduce 能用于并行化的 std::inner_product

#include <vector>
#include <functional>
#include <iostream>
#include <numeric>
#include <execution>
 
int main()
{
    std::vector<double> xvalues(10007, 1.0), yvalues(10007, 1.0);
 
    double result = std::transform_reduce(
        std::execution::par,
        xvalues.begin(), xvalues.end(),
        yvalues.begin(), 0.0
    );
    std::cout << result << '\n';
}

输出:

10007

参阅

对一个范围内的元素求和
(函数模板)
将一个函数应用于某一范围的各个元素,并在目标范围存储结果
(函数模板)
(C++17)
类似 std::accumulate,但不依序执行
(函数模板)