std::reduce
| Definido en el archivo de encabezado <numeric>
|
||
| (1) | ||
template<class InputIt> typename std::iterator_traits<InputIt>::value_type reduce( InputIt first, InputIt last); |
(desde C++17) (hasta C++20) |
|
template<class InputIt> constexpr typename std::iterator_traits<InputIt>::value_type reduce( InputIt first, InputIt last); |
(desde C++20) | |
template<class ExecutionPolicy, class ForwardIt> typename std::iterator_traits<ForwardIt>::value_type reduce( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last); |
(2) | (desde C++17) |
| (3) | ||
template<class InputIt, class T> T reduce(InputIt first, InputIt last, T init); |
(desde C++17) (hasta C++20) |
|
template<class InputIt, class T> constexpr T reduce(InputIt first, InputIt last, T init); |
(desde C++20) | |
template<class ExecutionPolicy, class ForwardIt, class T> T reduce(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, T init); |
(4) | (desde C++17) |
| (5) | ||
template<class InputIt, class T, class BinaryOp> T reduce(InputIt first, InputIt last, T init, BinaryOp binary_op); |
(desde C++17) (hasta C++17) |
|
template<class InputIt, class T, class BinaryOp> constexpr T reduce(InputIt first, InputIt last, T init, BinaryOp binary_op); |
(desde C++17) | |
template<class ExecutionPolicy, class ForwardIt, class T, class BinaryOp> T reduce(ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, T init, BinaryOp binary_op); |
(6) | (desde C++17) |
reduce(first, last, typename std::iterator_traits<InputIt>::value_type{}).reduce(first, last, init, std::plus<>()).init sobre binary_op. policy. Estas sobrecargas no participan en la resolución de sobrecarga a menos que std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> (hasta C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> (desde C++20) sea verdadera.El comportamiento es no-determinístico si binary_op es no-asociativa o no-conmutativa.
El comportamiento está indefinido si binary_op modifica cualquier elemento o invalida cualquier iterador en [first; last], incluyendo el iterador al final.
Parámetros
| first, last | - | El rango de elementos al cual aplicar el algoritmo. |
| init | - | El valor inicial de la suma generalizada |
| policy | - | La política de ejecución a usar. Véase política de ejecución para más detalles. |
| binary_op | - | FunctionObject, un objeto función binario que se aplicará en un orden inespecífico al resultado de desreferenciar los iteradores de entrada, los resultados de otras operaciones binarias binary_op e init.
|
| Requisitos de tipo | ||
-InputIt debe satisfacer los requisitos de InputIterator.
| ||
-ForwardIt debe satisfacer los requisitos de ForwardIterator.
| ||
-T debe satisfacer los requisitos de MoveConstructible. y binary_op(init, *first), binary_op(*first, init), binary_op(init, init), y binary_op(*first, *first) deben ser convertibles a T.
| ||
Valor de retorno
La suma generalizada de init y *first, *(first+1), ... *(last-1) sobre binary_op,
donde la suma generalizada GSUM(op, a
1, ..., a
N) se define de la manera siguiente:
- si N=1, a
1 - si N > 1, op(GSUM(op, b
1, ..., b
K), GSUM(op, b
M, ..., b
N)) donde
- b
1, ..., b
N puede ser cualquier permutación de a1, ..., aN y - 1 < K+1 = M ≤ N
- b
en otras palabras, reduce se comporta como std::accumulate, excepto que los elementos del rango pueden agruparse y reorganizarse en orden arbitrario.
Complejidad
O(last - first) aplicaciones de binary_op.
Excepciones
Las sobrecargas con un parámetro de plantilla llamado ExecutionPolicy (política de ejecución) reportan errores tales que:
- Si la ejecución de una función invocada como parte del algoritmo lanza una excepción y la política de ejecución es una de las tres políticas estándar, se llama a std::terminate. Para cualquier otra política de ejecución, el comportamiento está definido por la implementación.
- Si el algoritmo falla al asignar memoria, se lanza std::bad_alloc.
Notas
Si el rango está vacío, se devuelve init sin modificar.
Ejemplo
Comparación lado a lado entre reduce y std::accumulate:
#include <iostream>
#include <chrono>
#include <vector>
#include <numeric>
#include <execution>
int main()
{
const std::vector<double> v(10'000'007, 0.5);
{
const auto t1 = std::chrono::high_resolution_clock::now();
const double result = std::accumulate(v.cbegin(), v.cend(), 0.0);
const auto t2 = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double, std::milli> ms = t2 - t1;
std::cout << std::fixed << "resultado de std::accumulate " << result
<< " toma " << ms.count() << " ms\n";
}
{
const auto t1 = std::chrono::high_resolution_clock::now();
const double result = std::reduce(std::execution::par, v.cbegin(), v.cend());
const auto t2 = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double, std::milli> ms = t2 - t1;
std::cout << "resultado de std::reduce "
<< result << " toma " << ms.count() << " ms\n";
}
}
Posible salida:
resultado de std::accumulate 5000003.50000 toma 12.7365 ms
resultado de std::reduce 5000003.50000 toma 5.06423 ms
Véase también
| Suma un rango de elementos (plantilla de función) | |
| Aplica una función a un rango de elementos (plantilla de función) | |
(C++17) |
Aplica un invocable, luego reduce fuera de orden (plantilla de función) |