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 > |
(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 > |
(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.
Contenido |
[editar] 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. |
[editar] Valor de retorno
{std::ranges::next(std::move(first), last), std::move(f)}
[editar] Complejidad
Exactamente last
- first
aplicaciones de f
y proj
.
[editar] 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; |
[editar] 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
[editar] 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) |