std::inner_product
| ヘッダー <numeric> で定義 |
||
template< class InputIt1, class InputIt2, class T > T inner_product( InputIt1 first1, InputIt1 last1, |
(1) | (C++20 以降 constexpr) |
template< class InputIt1, class InputIt2, class T, class BinaryOp1, class BinaryOp2 > |
(2) | (C++20 以降 constexpr) |
範囲 [first1, last1) と、 std::distance(first1, last1) 個の要素からなる first2 で始まる範囲の内部積(積の和)を計算するか、順序付けられたマップ/リデュース操作を実行します。
T)を初期値 init で初期化し、その後、各イテレータ i1 が範囲 [first1, last1) 内で順番に処理され、それに対応するイテレータ i2 が first2 で始まる範囲から取得される際に、式 acc = acc + (*i1) * (*i2)(until C++20)acc = std::move(acc) + (*i1) * (*i2)(since C++20) を使用して変更されます。+ および * の組み込みの意味においては、これは 2 つの範囲の内部積を計算します。T)を初期値 init で初期化し、その後、各イテレータ i1 が範囲 [first1, last1) 内で順番に処理され、それに対応するイテレータ i2 が first2 で始まる範囲から取得される際に、式 acc = op1(acc, op2(*i1, *i2))(until C++20)acc = op1(std::move(acc), op2(*i1, *i2))(since C++20) を使用して変更されます。last2 が std::distance(first1, last1)番目の first2 の次のイテレータである場合、以下のいずれかの条件が満たされると、動作は未定義となります。
-
Tが CopyConstructible ではない。 -
Tが CopyAssignable ではない。 - op1 または op2 が、
[first1,last1)または[first2,last2)のいずれかの要素を変更する。 - op1 または op2 が、
[first1,last1]または[first2,last2]のいずれかのイテレータまたはサブ範囲を無効にする。
目次 |
[編集] パラメータ
| first1, last1 | - | 対象となる要素の 範囲 を定義するイテレータのペア |
| first2 | - | 2番目の要素範囲の開始位置 |
| init | - | 積の和の初期値 |
| op1 | - | 適用されるバイナリ演算関数オブジェクト。「合計」関数は、op2 の戻り値とアキュムレータの現在の値を取り、アキュムレータに格納される新しい値を生成します。 関数のシグネチャは以下と同等である必要があります。 Ret fun(const Type1 &a, const Type2 &b); シグネチャは const & を持つ必要はありません。 |
| op2 | - | 適用されるバイナリ演算関数オブジェクト。「積」関数は、各範囲から1つの値を取り、新しい値を生成します。 関数のシグネチャは以下と同等である必要があります。 Ret fun(const Type1 &a, const Type2 &b); シグネチャは const & を持つ必要はありません。 |
| 型要件 | ||
-InputIt1, InputIt2 は LegacyInputIterator の要件を満たす必要がある。 | ||
[編集] 戻り値
すべての変更後の acc。
[編集] 実装例
| inner_product (1) |
|---|
template<class InputIt1, class InputIt2, class T> constexpr // since C++20 T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init) { while (first1 != last1) { init = std::move(init) + (*first1) * (*first2); // std::move since C++20 ++first1; ++first2; } return init; } |
| inner_product (2) |
template<class InputIt1, class InputIt2, class T, class BinaryOp1, class BinaryOp2> constexpr // since C++20 T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init, BinaryOp1 op1, BinaryOp2 op2) { while (first1 != last1) { init = op1(std::move(init), op2(*first1, *first2)); // std::move since C++20 ++first1; ++first2; } return init; } |
[編集] 注記
このアルゴリズムの並列化可能なバージョンである std::transform_reduce は、op1 と op2 が可換かつ結合的であることを要求しますが、std::inner_product はそのような要件を課さず、常に指定された順序で操作を実行します。
[編集] 例
#include <functional> #include <iostream> #include <numeric> #include <vector> int main() { std::vector<int> a{0, 1, 2, 3, 4}; std::vector<int> b{5, 4, 2, 3, 1}; int r1 = std::inner_product(a.begin(), a.end(), b.begin(), 0); std::cout << "Inner product of a and b: " << r1 << '\n'; int r2 = std::inner_product(a.begin(), a.end(), b.begin(), 0, std::plus<>(), std::equal_to<>()); std::cout << "Number of pairwise matches between a and b: " << r2 << '\n'; }
出力
Inner product of a and b: 21 Number of pairwise matches between a and b: 2
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 242 | C++98 | op1 および op2 は副作用を持てない | それらは関係する範囲を変更できない |
[編集] 関連項目
| (C++17) |
呼び出し可能オブジェクトを適用し、順序不同に縮約する (関数テンプレート) |
| 範囲の要素を合計または畳み込む (関数テンプレート) | |
| 範囲の要素の部分和を計算する (関数テンプレート) |