Namespaces
Variants

std::inner_product

De es.cppreference.net
 
 
Biblioteca de algoritmos
Algoritmos restringidos y algoritmos sobre rangos (C++20)
Algoritmos restringidos, p. ej. ranges::copy, ranges::sort, ...
Operaciones de secuencia no modificadoras    
Operaciones por lotes
(C++17)
Operaciones de búsqueda
Operaciones de secuencia modificadoras
Operaciones de copia
(C++11)
(C++11)
Operaciones de intercambio
Operaciones de transformación
Operaciones de generación
Operaciones de eliminación
Operaciones de cambio de orden
(hasta C++17)(C++11)
(C++20)(C++20)
Operaciones de muestreo
(C++17)

Operaciones de ordenación y relacionadas
Operaciones de particionado
(C++11)    

Operaciones de ordenación
Operaciones de búsqueda binaria
(en rangos particionados)
Operaciones de conjuntos (en rangos ordenados)
Operaciones de mezcla (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
(C++11)
(C++17)
Operaciones de comparación lexicográfica
Operaciones de permutación


 
 
Definido en el encabezado <numeric>
template< class InputIt1, class InputIt2, class T >
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init );
(1) (constexpr desde 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 desde C++20)

Calcula el producto interior (es decir, suma de productos) o realiza una operación ordenada de mapa/reducción en el rango [first1, last1) y el rango de std::distance(first1, last1) elementos que comienza en first2.

1) Inicializa el acumulador acc (de tipo T) con el valor inicial init y luego lo modifica con la expresión acc = acc + (*i1) * (*i2)(hasta C++20)acc = std::move(acc) + (*i1) * (*i2)(desde C++20) para cada iterador i1 en el rango [first1, last1) en orden y su iterador correspondiente i2 en el rango que comienza en first2. Con el significado intrínseco de + y *, esto calcula el producto interior de los dos rangos.
2) Inicializa el acumulador acc (de tipo T) con el valor inicial init y luego lo modifica con la expresión acc = op1(acc, op2(*i1, *i2))(hasta C++20)acc = op1(std::move(acc), op2(*i1, *i2))(desde C++20) para cada iterador i1 en el rango [first1, last1) en orden y su iterador correspondiente i2 en el rango que comienza en first2.

Dado last2 como el std::distance(first1, last1)ésimo siguiente iterador de first2, si se cumple alguna de las siguientes condiciones, el comportamiento no está definido:

  • T no es CopyConstructible.
  • T no es CopyAssignable.
  • op1 o op2 modifica cualquier elemento de [first1, last1) o [first2, last2).
  • op1 o op2 invalida cualquier iterador o subrango en [first1, last1] o [first2, last2].

Parámetros

first1, last1 - el par de iteradores que definen el rango de elementos a
first2 - el inicio del segundo rango de elementos
init - valor inicial de la suma de los productos
op1 - objeto función de operación binaria que se aplicará. Esta función "suma" toma un valor devuelto por op2 y el valor actual del acumulador y produce un nuevo valor para almacenar en el acumulador.

La firma de la función debe ser equivalente a la siguiente:

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

La firma no necesita tener const &.
Los tipos Type1 y Type2 deben ser tales que los objetos de tipos T y Type3 puedan convertirse implícitamente a Type1 y Type2 respectivamente. El tipo Ret debe ser tal que un objeto de tipo T pueda asignarse un valor de tipo Ret. ​

op2 - objeto función de operación binaria que se aplicará. Esta función "producto" toma un valor de cada rango y produce un nuevo valor.

La firma de la función debe ser equivalente a la siguiente:

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

La firma no necesita tener const &.
Los tipos Type1 y Type2 deben ser tales que los objetos de tipos InputIt1 y InputIt2 puedan ser desreferenciados y luego convertidos implícitamente a Type1 y Type2 respectivamente. El tipo Ret debe ser tal que un objeto de tipo Type3 pueda asignarse un valor de tipo Ret. ​

Requisitos de tipo
-
InputIt1, InputIt2 debe cumplir los requisitos de LegacyInputIterator.

Valor de retorno

acc después de todas las modificaciones.

Posible implementación

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;
}

Notas

La versión paralelizable de este algoritmo, std::transform_reduce, requiere que op1 y op2 sean conmutativos y asociativos, pero std::inner_product no impone tal requisito, y siempre realiza las operaciones en el orden dado.

Ejemplo

#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';
}

Salida:

Inner product of a and b: 21
Number of pairwise matches between a and b: 2

Informes de defectos

Los siguientes informes de defectos que cambian el comportamiento se aplicaron retroactivamente a los estándares C++ previamente publicados.

DR Aplicado a Comportamiento según lo publicado Comportamiento correcto
LWG 242 C++98 op1 y op2 no podían tener efectos secundarios no pueden modificar los rangos involucrados

Véase también

aplica un invocable, luego reduce fuera de orden
(plantilla de función)
suma o pliega un rango de elementos
(plantilla de función)
calcula la suma parcial de un rango de elementos
(plantilla de función)