Namespaces
Variants

std::inner_product

ja.cppreference.net より
 
 
アルゴリズムライブラリ
制約付きアルゴリズムと範囲に対するアルゴリズム (C++20)
制約付きアルゴリズム(例: ranges::copy、ranges::sort、...)
ソートと関連操作
分割操作
(C++11)    

ソート操作
二分探索操作 (分割範囲に対する)
集合操作 (ソート済み範囲に対する)
        
マージ操作 (ソート済み範囲に対する)
ヒープ操作
最小値/最大値操作
(C++11)
(C++17)
辞書比較操作
順列操作


 
 
ヘッダ <numeric> で定義
template< class InputIt1, class InputIt2, class T >
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init );
(1) (C++20 以降 constexpr)
template< class InputIt1, class InputIt2, class T,
          class BinaryOp1, class BinaryOp2 >
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init,
                 BinaryOp1 op1, BinaryOp2 op2 );
(2) (C++20 以降 constexpr)

範囲 [first1, last1) と std::distance(first1, last1) の first2 から始まる範囲の要素の内積 (積の和) を計算するか、順序付き map/reduce 操作を実行します。

1) アキュムレータ acc (型は T) を初期値 init で初期化し、範囲 acc = acc + (*i1) * (*i2)(C++20 まで)acc = std::move(acc) + (*i1) * (*i2)(C++20 以降) 内のイテレータ i1 と、[first1, last1) の対応するイテレータ i2 (first2 から始まる範囲内) ごとに、式
で変更します。+ と * の組み込みの意味では、2 つの範囲の内積を計算します。
2) アキュムレータ acc (型は T) を初期値 init で初期化し、範囲 acc = op1(acc, op2(*i1, *i2))(C++20 まで)acc = op1(std::move(acc), op2(*i1, *i2))(C++20 以降) 内のイテレータ i1 と、[first1, last1) の対応するイテレータ i2 (first2 から始まる範囲内) ごとに、式
で変更します。

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 & が含まれている必要はありません。
型 Type1 と Type2 は、型 T と Type3 のオブジェクトがそれぞれ Type1 と Type2 に暗黙的に変換可能である必要があります。型 Ret は、型 T のオブジェクトに型 Ret の値を代入可能である必要があります。 ​

op2 - 適用される二項演算関数オブジェクト。この「積」関数は、各範囲から 1 つの値を受け取り、新しい値を生成します。

関数のシグネチャは以下と同等である必要があります:

Ret fun(const Type1 &a, const Type2 &b);

シグネチャに const & が含まれている必要はありません。
型 Type1 と Type2 は、型 InputIt1 と InputIt2 のオブジェクトを逆参照し、それぞれ Type1 と Type2 に暗黙的に変換可能である必要があります。型 Ret は、型 Type3 のオブジェクトに型 Ret の値を代入可能である必要があります。 ​

型要件
-
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 に副作用があってはならない 関与する範囲を変更できない

関連項目

呼び出し可能オブジェクトを適用し、順序を保証せずに結果を集約する
(関数テンプレート)
要素範囲を合計または畳み込む
(関数テンプレート)
要素範囲の部分和を計算する
(関数テンプレート)