std:: partial_sum
|
Definido en el encabezado
<numeric>
|
||
|
template
<
class
InputIt,
class
OutputIt
>
OutputIt partial_sum
(
InputIt first, InputIt last,
|
(1) | (constexpr desde C++20) |
|
template
<
class
InputIt,
class
OutputIt,
class
BinaryOp
>
OutputIt partial_sum
(
InputIt first, InputIt last,
|
(2) | (constexpr desde C++20) |
[
first
,
last
)
está vacío, no hace nada.
-
Crea un acumulador
acc
, cuyo tipo es el
value type
de
InputIt, y lo inicializa con * first . - Asigna acc a * d_first .
-
Para cada entero
i
en
[1,std:: distance ( first, last )), realiza las siguientes operaciones en orden:
Dado binary_op como la operación binaria real:
- Si se satisface cualquiera de las siguientes condiciones, el programa está mal formado:
-
-
El tipo de valor de
InputItno es construible desde * first . - acc no es escribible en d_first .
-
El resultado de
binary_op
(
acc,
*
iter
)
(hasta C++20)
binary_op
(
std
::
move
(
acc
)
,
*
iter
)
(desde C++20)
no es convertible implícitamente al tipo de valor de
InputIt.
-
El tipo de valor de
- Dado d_last como el iterador a ser devuelto , si alguna de las siguientes condiciones se satisface, el comportamiento es indefinido:
-
-
binary_op
modifica cualquier elemento de
[first,last)o[d_first,d_last). -
binary_op
invalida cualquier iterador o subrango en
[first,last]o[d_first,d_last].
-
binary_op
modifica cualquier elemento de
- ↑ El valor real que se asignará es el resultado de la asignación en el paso anterior. Asumimos que el resultado de la asignación es acc aquí.
Contenidos |
Parámetros
| first, last | - | el par de iteradores que define el rango de elementos a sumar |
| d_first | - | el inicio del rango destino; puede ser igual a first |
| op | - |
objeto función de operación binaria que será aplicado.
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
&
.
|
| Requisitos de tipo | ||
-
InputIt
debe cumplir con los requisitos de
LegacyInputIterator
.
|
||
-
OutputIt
debe cumplir con los requisitos de
LegacyOutputIterator
.
|
||
Valor de retorno
Iterador al elemento después del último elemento escrito, o
d_first
si
[
first
,
last
)
está vacío.
Complejidad
Dado N como std:: distance ( first, last ) :
Implementación posible
| partial_sum (1) |
|---|
template<class InputIt, class OutputIt> constexpr // desde C++20 OutputIt partial_sum(InputIt first, InputIt last, OutputIt d_first) { if (first == last) return d_first; typename std::iterator_traits<InputIt>::value_type sum = *first; *d_first = sum; while (++first != last) { sum = std::move(sum) + *first; // std::move desde C++20 *++d_first = sum; } return ++d_first; // o, desde C++14: // return std::partial_sum(first, last, d_first, std::plus<>()); } |
| partial_sum (2) |
template<class InputIt, class OutputIt, class BinaryOp> constexpr // desde C++20 OutputIt partial_sum(InputIt first, InputIt last, OutputIt d_first, BinaryOp op) { if (first == last) return d_first; typename std::iterator_traits<InputIt>::value_type acc = *first; *d_first = acc; while (++first != last) { acc = op(std::move(acc), *first); // std::move desde C++20 *++d_first = acc; } return ++d_first; } |
Notas
acc se introdujo debido a la resolución de LWG issue 539 . La razón de usar acc en lugar de sumar directamente los resultados (es decir, * ( d_first + 2 ) = ( * first + * ( first + 1 ) ) + * ( first + 2 ) ; ) es porque la semántica de este último es confusa si los siguientes tipos no coinciden:
-
el tipo de valor de
InputIt -
el(los) tipo(s) escribible(s) de
OutputIt - los tipos de los parámetros de operator + o op
- el tipo de retorno de operator + o op
acc sirve como el objeto intermedio para almacenar y proporcionar los valores para cada paso del cálculo:
-
su tipo es el tipo de valor de
InputIt - se escribe en d_first
- su valor se pasa a operator + o op
- almacena el valor de retorno de operator + o op
enum not_int { x = 1, y = 2 }; char i_array[4] = {100, 100, 100, 100}; not_int e_array[4] = {x, x, y, y}; int o_array[4]; // CORRECTO: utiliza operator+(char, char) y asigna valores char al array int std::partial_sum(i_array, i_array + 4, o_array); // ERROR: no se pueden asignar valores not_int al array int std::partial_sum(e_array, e_array + 4, o_array); // CORRECTO: realiza conversiones cuando es necesario // 1. crea "acc" de tipo char (el tipo de valor) // 2. los argumentos char se usan para multiplicación long (char -> long) // 3. el producto long se asigna a "acc" (long -> char) // 4. "acc" se asigna a un elemento de "o_array" (char -> int) // 5. vuelve al paso 2 para procesar los elementos restantes en el rango de entrada std::partial_sum(i_array, i_array + 4, o_array, std::multiplies<long>{});
Ejemplo
#include <functional> #include <iostream> #include <iterator> #include <numeric> #include <vector> int main() { std::vector<int> v(10, 2); // v = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2} std::cout << "Los primeros " << v.size() << " números pares son: "; // escribir el resultado al flujo cout std::partial_sum(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " ")); std::cout << '\n'; // escribir el resultado de vuelta al vector v std::partial_sum(v.cbegin(), v.cend(), v.begin(), std::multiplies<int>()); std::cout << "Las primeras " << v.size() << " potencias de 2 son: "; for (int n : v) std::cout << n << ' '; std::cout << '\n'; }
Salida:
Los primeros 10 números pares son: 2 4 6 8 10 12 14 16 18 20 Las primeras 10 potencias de 2 son: 2 4 8 16 32 64 128 256 512 1024
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Aplicado a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 242 | C++98 | op no podía tener efectos secundarios | no puede modificar los rangos involucrados |
| LWG 539 | C++98 |
faltaban los requisitos de tipo necesarios para que las
evaluaciones de resultados y asignaciones fueran válidas |
añadidos |
Véase también
|
calcula las diferencias entre elementos adyacentes en un rango
(plantilla de función) |
|
|
suma o pliega un rango de elementos
(plantilla de función) |
|
|
(C++17)
|
similar a
std::partial_sum
, incluye el
i
ésimo
elemento de entrada en la
i
ésima
suma
(plantilla de función) |
|
(C++17)
|
similar a
std::partial_sum
, excluye el
i
ésimo
elemento de entrada de la
i
ésima
suma
(plantilla de función) |