std::adjacent_difference
ヘッダ <numeric> で定義
|
||
(1) | ||
template< class InputIt, class OutputIt > OutputIt adjacent_difference( InputIt first, InputIt last, |
(C++20未満) | |
template< class InputIt, class OutputIt > constexpr OutputIt adjacent_difference( InputIt first, InputIt last, |
(C++20以上) | |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 > ForwardIt2 adjacent_difference( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, |
(2) | (C++17以上) |
(3) | ||
template< class InputIt, class OutputIt, class BinaryOperation > OutputIt adjacent_difference( InputIt first, InputIt last, |
(C++20未満) | |
template< class InputIt, class OutputIt, class BinaryOperation > constexpr OutputIt adjacent_difference( InputIt first, InputIt last, |
(C++20以上) | |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryOperation > ForwardIt2 adjacent_difference( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, |
(4) | (C++17以上) |
範囲 [first, last)
の隣接する要素それぞれの組の2つめと1つめの差を計算し、その結果を d_first + 1
から始まる範囲に書き込みます。 *first
のコピーが無変更で *d_first
に書き込まれます。
InputIt
の値型である累積変数 acc
を作成し、それを *first で初期化し、その結果を *d_first に代入します。
その後、 [first + 1, last)
内のすべてのイテレータ i
について、順番に、型が InputIt
の値型であるオブジェクト val
を作成し、それを *i で初期化し、 val - acc (C++20未満)val - std::move(acc) (C++20以上) (オーバーロード (1)) または op(val, acc) (C++20未満)op(val, std::move(acc)) (C++20以上) (オーバーロード (3)) を計算し、その結果を *(d_first + (i - first)) に代入し、 val
から acc
にムーブ代入します。[1, last - first - 1]
内のすべての d
について、型が ForwardIt1 の値型であるオブジェクトを作成し、それを *(first + d) - *(first + d - 1) (オーバーロード (2)) または op(*(first + d), *(first + d - 1)) (オーバーロード (4)) で初期化し、その結果を *(d_first + d) に代入します。
これは policy
に従って実行されます。 このオーバーロードは、std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> が true である場合にのみ、オーバーロード解決に参加します。以下の操作と同等です。
*(d_first) = *first; *(d_first+1) = *(first+1) - *(first); *(d_first+2) = *(first+2) - *(first+1); *(d_first+3) = *(first+3) - *(first+2); ...
|
(C++11未満) |
|
(C++11以上) |
目次 |
[編集] 引数
first, last | - | 要素の範囲 |
d_first | - | 書き込む範囲の先頭 |
policy | - | 使用する実行ポリシー。 詳細は実行ポリシーを参照してください |
op | - | 適用される二項演算関数オブジェクト。 関数のシグネチャは以下と同等であるべきです。 Ret fun(const Type1 &a, const Type2 &b); シグネチャが const & を持つ必要はありません。 |
型の要件 | ||
-InputIt は LegacyInputIterator の要件を満たさなければなりません。 InputIt の値型は MoveAssignable でなければならず、 *first の型から構築可能でなければなりません。
| ||
-OutputIt は LegacyOutputIterator の要件を満たさなければなりません。 acc (累積値) と val - acc または op(val, acc) (C++20未満)val - std::move(acc) または op(val, std::move(acc)) (C++20以上) の結果はどちらも OutputIt に書き込み可能でなければなりません。
| ||
-ForwardIt1, ForwardIt2 は LegacyForwardIterator の要件を満たさなければなりません。 ForwardIt1 の値型は CopyConstructible でなければならず、式 *first - *first または op(*first, *first) から構築可能でなければならず、 ForwardIt2 の値型に代入可能でなければなりません。
|
[編集] 戻り値
書き込まれた最後の要素の次の要素を指すイテレータ。
[編集] ノート
first == last
の場合、この関数は効果を持たず、単に d_first
を返します。
[編集] 計算量
ちょうど (last - first) - 1
回の二項演算の適用。
[編集] 例外
テンプレート引数 ExecutionPolicy
を持つオーバーロードは以下のようにエラーを報告します。
- アルゴリズムの一部として呼び出された関数の実行が例外を投げ、
ExecutionPolicy
が標準のポリシーのいずれかの場合は、 std::terminate が呼ばれます。 それ以外のあらゆるExecutionPolicy
については、動作は処理系定義です。 - アルゴリズムがメモリの確保に失敗した場合は、 std::bad_alloc が投げられます。
[編集] 実装例
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; } |
2つめのバージョン |
template<class InputIt, class OutputIt, class BinaryOperation> constexpr // since C++20 OutputIt adjacent_difference(InputIt first, InputIt last, OutputIt d_first, BinaryOperation 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; } |
[編集] 例
#include <numeric> #include <vector> #include <array> #include <iostream> #include <functional> #include <iterator> int main() { // デフォルトの実装 - 2つの隣接する項目間の差 std::vector v {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}; std::adjacent_difference(v.begin(), v.end(), v.begin()); for (auto n : v) std::cout << n << ' '; std::cout << '\n'; // フィボナッチ std::array<int, 10> a {1}; adjacent_difference(begin(a), std::prev(end(a)), std::next(begin(a)), std::plus<> {}); copy(begin(a), end(a), std::ostream_iterator<int> {std::cout, " "}); }
出力:
2 2 2 2 2 2 2 2 2 2 1 1 2 3 5 8 13 21 34 55
[編集] 関連項目
指定範囲の要素の部分和を計算します (関数テンプレート) | |
指定範囲の要素を合計します (関数テンプレート) |