std::adjacent_difference
定义在头文件 <numeric> 中 |
||
template< class InputIt, class OutputIt > OutputIt adjacent_difference( InputIt first, InputIt last, |
(1) | (从 C++20 开始为 constexpr) |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 > |
(2) | (从 C++17 开始) |
template< class InputIt, class OutputIt, class BinaryOp > OutputIt adjacent_difference( InputIt first, InputIt last, |
(3) | (从 C++20 开始为 constexpr) |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryOp > |
(4) | (从 C++17 开始) |
设 T
为 decltype(first) 的值类型。
[
first,
last)
为空,则不执行任何操作。- 创建一个类型为
T
的累加器 acc,并用 *first 初始化它。 - 将 acc 赋值给 *d_first。
- 对于
[
++first,
last)
中的每个迭代器 iter,按顺序执行以下操作
T
的对象 val,并用 *iter 初始化它。[
first,
last)
为空,则不执行任何操作。- 将 *first 赋值给 *d_first。
- 对于
[
1,
std::distance(first, last))
中的每个整数 i,按顺序执行以下操作
th 迭代器,prev 是 first 的下一个 i - 1
th 迭代器。
th 迭代器。
给定 binary_op 作为实际的二元运算
- 如果以下任何条件满足,程序格式错误
- 对于重载 (1,3)
-
T
不能从 *first 构造。 - acc 不能写入 d_first。
- binary_op(val, acc)(直到 C++20)binary_op(val, std::move(acc))(自 C++20 起) 的结果不能写入 d_first。
-
- 对于重载 (2,4)
- *first 不能写入 d_first。
- binary_op(*first, *first) 的结果不能写入 d_first。
- 给定 d_last 作为要 返回 的迭代器,如果以下任何条件满足,行为未定义
|
(自 C++20 起) |
- 对于重载 (2,4),
[
first,
last)
和[
d_first,
d_last)
重叠。 - binary_op 修改
[
first,
last)
或[
d_first,
d_last)
中的任何元素。 - binary_op 使
[
first,
last]
或[
d_first,
d_last]
中的任何迭代器或子范围失效。
- 对于重载 (2,4),
内容 |
[edit] 参数
first, last | - | 元素范围 |
d_first | - | 目标范围的开始 |
policy | - | 要使用的执行策略。有关详细信息,请参见 执行策略。 |
op | - | 要应用的二元运算函数对象。 函数的签名应等效于以下内容 Ret fun(const Type1 &a, const Type2 &b); 签名不需要具有 const &。 |
类型要求 | ||
-InputIt 必须满足 LegacyInputIterator 的要求。 | ||
-OutputIt 必须满足 LegacyOutputIterator 的要求。 | ||
-ForwardIt1, ForwardIt2 必须满足 LegacyForwardIterator 的要求。 |
[edit] 返回值
指向写入的最后一个元素之后的元素的迭代器,如果 [
first,
last)
为空,则返回 d_first。
[edit] 复杂度
给定 N 作为 std::distance(first, last)
[edit] 异常
具有名为 ExecutionPolicy
的模板参数的重载报告错误如下
- 如果作为算法的一部分调用的函数的执行抛出异常,并且
ExecutionPolicy
是 标准策略 之一,则调用 std::terminate。对于任何其他ExecutionPolicy
,行为是实现定义的。 - 如果算法无法分配内存,则抛出 std::bad_alloc。
[edit] 可能的实现
adjacent_difference (1) |
---|
template<class InputIt, class OutputIt> constexpr // since C++20 OutputIt adjacent_difference(InputIt first, InputIt last, OutputIt d_first) { if (first == last) return d_first; typedef typename std::iterator_traits<InputIt>::value_type value_t; value_t acc = *first; *d_first = acc; while (++first != last) { value_t val = *first; *++d_first = val - std::move(acc); // std::move since C++20 acc = std::move(val); } return ++d_first; } |
adjacent_difference (3) |
template<class InputIt, class OutputIt, class BinaryOp> constexpr // since C++20 OutputIt adjacent_difference(InputIt first, InputIt last, OutputIt d_first, BinaryOp op) { if (first == last) return d_first; typedef typename std::iterator_traits<InputIt>::value_type value_t; value_t acc = *first; *d_first = acc; while (++first != last) { value_t val = *first; *++d_first = op(val, std::move(acc)); // std::move since C++20 acc = std::move(val); } return ++d_first; } |
[edit] 注意
引入 acc 是因为解决了 LWG 问题 539。使用 acc 而不是直接计算差值的原因是,如果以下类型不匹配,则后者的语义会让人困惑
InputIt
的值类型OutputIt
的可写类型(s)- operator- 或 op 的参数的类型
- operator- 或 op 的返回值类型
acc 用作缓存迭代元素值的中间对象
- 它的类型是
InputIt
的值类型 - 写入 d_first 的值(即 operator- 或 op 的返回值) 被赋值给它
- 它的值被传递给 operator- 或 op
char i_array[4] = {100, 100, 100, 100}; int o_array[4]; // OK: performs conversions when needed // 1. creates “acc” of type char (the value type) // 2. “acc” is assigned to the first element of “o_array” // 3. the char arguments are used for long multiplication (char -> long) // 4. the long product is assigned to the output range (long -> int) // 5. the next value of “i_array” is assigned to “acc” // 6. go back to step 3 to process the remaining elements in the input range std::adjacent_difference(i_array, i_array + 4, o_array, std::multiplies<long>{});
[edit] 示例
#include <array> #include <functional> #include <iostream> #include <iterator> #include <numeric> #include <vector> void println(auto comment, const auto& sequence) { std::cout << comment; for (const auto& n : sequence) std::cout << n << ' '; std::cout << '\n'; }; int main() { // Default implementation - the difference between two adjacent items std::vector v{4, 6, 9, 13, 18, 19, 19, 15, 10}; println("Initially, v = ", v); std::adjacent_difference(v.begin(), v.end(), v.begin()); println("Modified v = ", v); // Fibonacci std::array<int, 10> a {1}; std::adjacent_difference(std::begin(a), std::prev(std::end(a)), std::next(std::begin(a)), std::plus<>{}); println("Fibonacci, a = ", a); }
输出
Initially, v = 4 6 9 13 18 19 19 15 10 Modified v = 4 2 3 4 5 1 0 -4 -5 Fibonacci, a = 1 1 2 3 5 8 13 21 34 55
[edit] 缺陷报告
以下行为更改缺陷报告已追溯应用于以前发布的 C++ 标准。
DR | 应用于 | 发布的行为 | 正确行为 |
---|---|---|---|
LWG 242 | C++98 | op 不能有副作用 | 它不能修改 所涉及的范围 |
LWG 539 | C++98 | 结果所需的类型要求丢失 评估和赋值的有效性验证丢失 |
添加 |
LWG 3058 | C++17 | 对于重载 (2,4),每次调用 的 operator- 或 op 的结果被赋值给一个临时 对象,该对象被赋值给输出范围 |
将结果 直接分配给输出 范围 |
[编辑] 另请参阅
计算一系列元素的偏和 (函数模板) | |
对一系列元素进行求和或折叠 (函数模板) |