std::ranges::for_each, std::ranges::for_each_result
| Definido en el archivo de encabezado <algorithm>
|
||
| Signatura de la llamada |
||
template< std::input_iterator I, std::sentinel_for<I> S, class Proj = std::identity, std::indirectly_unary_invocable<std::projected<I, Proj>> Fun > constexpr for_each_result<I, Fun> for_each( I first, S last, Fun f, Proj proj = {} ); |
(1) | (desde C++20) |
template< ranges::input_range R, class Proj = std::identity, std::indirectly_unary_invocable<std::projected<ranges::iterator_t<R>, Proj>> Fun > constexpr for_each_result<ranges::borrowed_iterator_t<R>, Fun> for_each( R&& r, Fun f, Proj proj = {} ); |
(2) | (desde C++20) |
| Tipos auxiliares |
||
template< class I, class F > using for_each_result = ranges::in_fun_result<I, F>; |
(3) | (desde C++20) |
f al resultado del valor proyectado por cada iterador en el rango [first, last), en orden. r como el rango fuente, como si usara ranges::begin(r) como first y ranges::end(r) como last.Para ambas sobrecargas, si el tipo de iterador es mutable, f puede modificar los elementos del rango a través del iterador desreferenciado. Si f devuelve un resultado, el resultado se ignora.
Las entidades similares a funciones descritas en esta página son niebloids, es decir:
- Las listas de argumentos de plantilla explícitas no se pueden especificar al llamar a cualquiera de ellas.
- Ninguna de ellas es visible para la búsqueda dependiente de argumentos.
- Cuando alguna de ellas se encuentra mediante la búsqueda normal no calificada como el nombre a la izquierda del operador de llamada a función, se inhibe la búsqueda dependiente de argumentos.
En la práctica, pueden implementarse como objetos función o con extensiones de compilador especiales.
Parámetros
| first, last | - | Par iterador-centinela que denota el rango a aplicar a la función. |
| r | - | El rango de elementos a los que aplicar la función. |
| f | - | La función a aplicar al rango proyectado. |
| proj | - | Proyección a aplicar a los elementos. |
Valor de retorno
{std::ranges::next(std::move(first), last), std::move(f)}
Complejidad
Exactamente last - first aplicaciones de f y proj.
Posible implementación
struct for_each_fn {
template<std::input_iterator I, std::sentinel_for<I> S, class Proj = std::identity,
std::indirectly_unary_invocable<std::projected<I, Proj>> Fun>
constexpr ranges::for_each_result<I, Fun>
operator()(I first, S last, Fun f, Proj proj = {}) const
{
for (; first != last; ++first) {
std::invoke(f, std::invoke(proj, *first));
}
return {std::move(first), std::move(f)};
}
template<ranges::input_range R, class Proj = std::identity,
std::indirectly_unary_invocable<std::projected<ranges::iterator_t<R>, Proj>> Fun>
constexpr ranges::for_each_result<ranges::borrowed_iterator_t<R>, Fun>
operator()(R&& r, Fun f, Proj proj = {}) const
{
return (*this)(ranges::begin(r), ranges::end(r), std::move(f), std::ref(proj));
}
};
inline constexpr for_each_fn for_each;
|
Ejemplo
El siguiente ejemplo usa una expresión lambda para incrementar todos los elementos de un vector y luego usa un operador operator() sobrecargado en un objeto función para calcular su suma. Ten en cuenta que para calcular la suma, se recomienda utilizar el algoritmo dedicado std::accumulate.
#include <algorithm>
#include <cassert>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
struct Suma
{
void operator()(int n) { suma += n; }
int suma{0};
};
int main()
{
std::vector<int> nums{3, 4, 2, 8, 15, 267};
auto imprimir = [](const auto& n) { std::cout << ' ' << n; };
namespace ranges = std::ranges;
std::cout << "antes:";
ranges::for_each(std::as_const(nums), imprimir);
imprimir('\n');
ranges::for_each(nums, [](int& n){ ++n; });
// llama a Suma::operator() para cada número
auto [i, s] = ranges::for_each(nums.begin(), nums.end(), Suma());
assert(i == nums.end());
std::cout << "después: ";
ranges::for_each(nums.cbegin(), nums.cend(), imprimir);
std::cout << "\n" "suma: " << s.suma << '\n';
using Par = std::pair<int, std::string>;
std::vector<Par> pares{{1,"uno"}, {2,"dos"}, {3,"tres"}};
std::cout << "proyectar el elemento Par::first: ";
ranges::for_each(pares, imprimir, [](const Par& p) { return p.first; });
std::cout << "\n" "proyectar el elemento Par::second:";
ranges::for_each(pares, imprimir, &Par::second);
imprimir('\n');
}
Salida:
antes: 3 4 2 8 15 267
después: 4 5 3 9 16 268
suma: 305
proyectar el elemento Par::first: 1 2 3
proyectar el elemento Par::second: uno dos tres
Véase también
Bucle for basado en rango
|
Ejecuta un bucle sobre un rango (desde C++11) |
(C++20) |
Aplica una función a un rango de elementos. (niebloid) |
(C++20) |
Aplica un objeto función a los primeros n elementos de una secuencia. (niebloid) |
| Aplica una función a un rango de elementos. (plantilla de función) |