std::exclusive_scan() 算法
- 自 C++20 起
- 自 C++17 起
// (1)
template< class InputIt, class OutputIt >
constexpr OutputIt exclusive_scan( InputIt first, InputIt last, OutputIt d_first );
// (2)
template< class InputIt, class OutputIt, class BinaryOperation >
constexpr OutputIt exclusive_scan( InputIt first, InputIt last, OutputIt d_first, BinaryOperation binary_op );
// (3)
template< class InputIt, class OutputIt, class BinaryOperation, class T >
constexpr OutputIt exclusive_scan( InputIt first, InputIt last, OutputIt d_first, BinaryOperation binary_op, T init );
// (4)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
ForwardtIt2 exclusive_scan( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first );
// (5)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryOperation >
ForwardIt2 exclusive_scan( ExecutionPolicy&& policy,
ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first,
BinaryOperation binary_op );
// (6)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryOperation, class T >
ForwardIt2 exclusive_scan( ExecutionPolicy&& policy,
ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first,
BinaryOperation binary_op, T init );
// (1)
template< class InputIt, class OutputIt >
OutputIt exclusive_scan( InputIt first, InputIt last, OutputIt d_first );
// (2)
template< class InputIt, class OutputIt, class BinaryOperation >
OutputIt exclusive_scan( InputIt first, InputIt last, OutputIt d_first, BinaryOperation binary_op );
// (3)
template< class InputIt, class OutputIt, class BinaryOperation, class T >
OutputIt exclusive_scan( InputIt first, InputIt last, OutputIt d_first, BinaryOperation binary_op, T init );
// (4)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
ForwardtIt2 exclusive_scan( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first );
// (5)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryOperation >
ForwardIt2 exclusive_scan( ExecutionPolicy&& policy,
ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first,
BinaryOperation binary_op );
// (6)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryOperation, class T >
ForwardIt2 exclusive_scan( ExecutionPolicy&& policy,
ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first,
BinaryOperation binary_op, T init );
使用 binary_op
(对于重载 (1, 4),使用 std::plus<>()
)计算一个专属前缀和操作,范围为 [first
; last
),使用 init
作为初始值(如果提供),并将结果写入从 d_first
开始的范围。
"专属" 意味着第 i 个输入元素不包含在第 i 个和中。
求和操作可以按任意顺序执行,如果 binary_op
不具有结合性,则行为不确定。
形式上,通过 [d_first
; d_first + (last - first)
) 中的每个迭代器 i
分配值
- (1, 2, 4, 5) 对于 [
first
;first + (i - d_first + 1) )
中每个j
,*j
... 的广义非交换和,通过binary_op
计算 - (3, 6) 对于 [
first
;first + (i - d_first + 1))
中每个j
,init
,*j
... 的广义非交换和,通过binary_op
计算
其中广义非交换和 GNSUM(op, a1, ..., aN)
定义如下:
-
如果
N = 1
,则为a1
-
如果
N > 1
,则对于任何K
且1 < K + 1 = M ≤ N
,为op(GNSUM(op, a1, ..., aK)
,GNSUM(op, aM, ..., aN))
-
(4 - 6) 与 (1 - 3) 相同,但根据策略执行。
重载决议这些重载仅在
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 起)
binary_op
不应使迭代器(包括结束迭代器)或子范围失效,也不应修改范围 [first
, last
) 或 [d_first
, d_first + (last - first)
) 中的元素。
否则,行为未定义
.参数
first last | 要求和的元素范围。 |
d_first | 目标范围的开始;可以等于 |
init | 广义和的初始值。 |
策略 | 要使用的执行策略。有关详细信息,请参阅执行策略。 |
binary_op | 二元函数对象,将以未指定顺序应用于解引用输入迭代器的结果、其他 |
类型要求
InputIt | LegacyInputIterator |
OutputIt | LegacyOutputIterator |
ForwardIt1 ForwardIt2 | LegacyForwardIterator |
T
(如果提供了init
)必须满足MoveConstructible
的要求。以下表达式必须可转换为T
binary_op(init, *first)
binary_op(init, init)
binary_op(*first, *first)
返回值
指向已写入的最后一个元素之后的元素的迭代器。
复杂度
O(last - first) 次 binary_op
应用。
异常
带有模板参数 ExecutionPolicy
的重载报告错误如下
- 如果作为算法一部分调用的函数执行抛出异常,并且
ExecutionPolicy
是标准策略之一,则调用std::terminate
。对于任何其他ExecutionPolicy
,行为是实现定义的. - 如果算法未能分配内存,则抛出
std::bad_alloc
。
示例
#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
int main()
{
std::vector data {3, 1, 4, 1, 5, 9, 2, 6};
std::cout << "Exclusive sum: ";
std::exclusive_scan(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "),
0);
std::cout << "\nInclusive sum: ";
std::inclusive_scan(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n\nExclusive product: ";
std::exclusive_scan(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "),
1, std::multiplies<>{});
std::cout << "\nInclusive product: ";
std::inclusive_scan(data.begin(), data.end(),
std::ostream_iterator<int>(std::cout, " "),
std::multiplies<>{});
}
Exclusive sum: 0 3 4 8 9 14 23 25
Inclusive sum: 3 4 8 9 14 23 25 31
Exclusive product: 1 3 3 12 12 60 540 1080
Inclusive product: 3 3 12 12 60 540 1080 6480