Namespaces
Variants

std::inner_product

От ru.cppreference.net
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы над диапазонами (C++20)
Ограниченные алгоритмы, например ranges::copy, ranges::sort, ...
Немодифицирующие операции над последовательностями    
Пакетные операции
(C++17)
Операции поиска
Модифицирующие операции над последовательностями
Операции копирования
(C++11)
(C++11)
Операции обмена
Операции преобразования
Операции генерации
Операции удаления
Операции изменения порядка
(до C++17)(C++11)
(C++20)(C++20)
Операции выборки
(C++17)

Операции сортировки и связанные с ними
Операции разбиения
(C++11)    

Операции сортировки
Операции бинарного поиска
(на разделённых диапазонах)
Операции над множествами (на отсортированных диапазонах)
Операции слияния (на отсортированных диапазонах)
Операции с пирамидой
Операции поиска минимума/максимума
(C++11)
(C++17)
Операции лексикографического сравнения
Операции перестановки


Политики выполнения (C++17)
(только для демонстрации*)(C++26)

Численные операции
(C++11)
(C++17)
(C++17)    

Специализированные <memory> алгоритмы

Специализированные <random> алгоритмы
Библиотека C









 
 
Определён в заголовке <numeric>
template< class InputIt1, class InputIt2, class T >
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init );
(1) (constexpr начиная с C++20)
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) (constexpr начиная с C++20)

Вычисляет внутреннее произведение (т.е. сумму произведений) или выполняет упорядоченную операцию map/reduce над диапазоном [first1, last1) и диапазоном из std::distance(first1, last1) элементов, начиная с first2.

1) Инициализирует аккумулятор acc (типа T) начальным значением init, а затем изменяет его с помощью выражения acc = acc + (*i1) * (*i2)(до C++20)acc = std::move(acc) + (*i1) * (*i2)(начиная с C++20) для каждого итератора i1 в диапазоне [first1, last1) по порядку и соответствующего ему итератора i2 в диапазоне, начинающемся с first2. При встроенном значении + и * это вычисляет внутреннее произведение двух диапазонов.
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 - начало второго диапазона элементов
init - начальное значение суммы произведений
op1 - бинарный функциональный объект, который будет применяться. Эта функция «суммы» принимает значение, возвращаемое op2, и текущее значение аккумулятора, и создаёт новое значение для сохранения в аккумуляторе.

Сигнатура функции должна быть эквивалентна следующей:

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

Сигнатура не обязательно должна содержать const &.
Типы Type1 и Type2 должны быть такими, чтобы объекты типов T и Type3 могли быть неявно преобразованы в Type1 и Type2 соответственно. Тип Ret должен быть таким, чтобы объекту типа T можно было присвоить значение типа Ret. ​

op2 - бинарный функциональный объект, который будет применяться. Эта функция «произведения» принимает по одному значению из каждого диапазона и создаёт новое значение.

Сигнатура функции должна быть эквивалентна следующей:

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 не могли иметь побочных эффектов они не могут изменять задействованные диапазоны

Смотрите также

применяет вызываемый объект, затем сводит не по порядку
(шаблон функции)
суммирует или свёртывает диапазон элементов
(шаблон функции)
вычисляет частичную сумму диапазона элементов
(шаблон функции)