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,按顺序执行以下操作:
给定 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),
目录 |
[编辑] 参数
first, last | - | 定义要操作的元素 范围 的迭代器对 |
d_first | - | 目标范围的开头 |
policy | - | 要使用的 执行策略 |
op | - | 将应用的二元操作函数对象。 函数的签名应等效于以下内容 Ret fun(const Type1 &a, const Type2 &b); 签名不需要有 const &。 |
类型要求 | ||
-InputIt 必须满足 LegacyInputIterator 的要求。 | ||
-OutputIt 必须满足 LegacyOutputIterator 的要求。 | ||
-ForwardIt1, ForwardIt2 必须满足 LegacyForwardIterator 的要求。 |
[编辑] 返回值
指向所写入的最后一个元素之后的迭代器,若 [
first,
last)
为空则为 d_first。
[编辑] 复杂度
给定 N 为 std::distance(first, last)
[编辑] 异常
带有模板参数 ExecutionPolicy
的重载按如下方式报告错误
- 若作为算法一部分调用的函数执行抛出异常且
ExecutionPolicy
为 标准策略 之一,则调用 std::terminate。对于任何其他ExecutionPolicy
,行为是实现定义的。 - 如果算法未能分配内存,则抛出 std::bad_alloc。
[编辑] 可能的实现
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; } |
[编辑] 注意
引入 acc 是因为 LWG issue 539 的决议。使用 acc 而非直接计算差值的原因是,若以下类型不匹配,后者的语义会令人困惑:
InputIt
的值类型OutputIt
的可写类型- 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>{});
[编辑] 示例
#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
[编辑] 缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
LWG 242 | C++98 | op 不得有副作用 | 它不能修改 涉及的范围 |
LWG 539 | C++98 | 结果所需类型要求 评估和赋值缺失 |
已添加 |
LWG 3058 | C++17 | 对于重载 (2,4),每次调用 operator- 或 op 的结果都会赋值给一个临时 对象,然后该对象再赋值给输出范围 |
直接将结果赋值 给输出 范围 |
[编辑] 参阅
计算一个范围元素的部分和 (函数模板) | |
对一个范围的元素进行求和或折叠 (函数模板) |