¿Es posible utilizar un número dinámico de adaptadores de rango?
Soy bastante nuevo en el uso de rangos y quería saber si hay alguna manera de aplicar un número dinámico de adaptadores de rango. He estado jugando con algún código por un tiempo y también he hecho algunas búsquedas, pero sin éxito.
#include <iostream>
#include <ranges>
int main() {
auto output = std::ranges::views::iota(2, 100);
for (int i = 2; i < 100; i++) {
output = output | std::ranges::views::filter([i](int num){ return num % i != 0 || num == i; });
}
std::cout << "El décimo número primo es: " << output[9] << "\n";
}
Básicamente, quiero algo como esto, pero esto da un error de compilación (no match for 'operator='
). Parece que cada aplicación de un adaptador de rango requiere un nuevo tipo, por lo que no podemos crear este rango de manera dinámica. ¿Hay alguna forma de evitar esto?
davy.ai
Hasta ahora, no es posible aplicar un número dinámico de adaptadores de rango en C++20. Cada aplicación de un adaptador de rango crea un nuevo tipo y no hay forma de crear un tipo en tiempo de ejecución. Por lo tanto, no es posible aplicar dinámicamente un número variable de adaptadores de rango a un rango.
Una solución alternativa a esta limitación es utilizar un enfoque de meta-programación de plantillas. Esto implica definir una función de plantilla recursiva que toma un rango y una lista de adaptadores de rango como argumentos y aplica los adaptadores uno por uno utilizando el operador pipe. El resultado final es un rango adaptado con todos los adaptadores especificados.
Aquí hay un ejemplo de implementación de una función de plantilla que aplica un número dinámico de adaptadores de rango:
“`c++(r); (r) | adaptador, adaptadores_restantes);
template
constexpr auto apply_range_adaptors(R&& r, Adaptors&&… adaptadores) {
if constexpr (sizeof…(adaptadores) == 0) {
return std::forward
} else {
auto adaptador = std::get<0>(std::forward_as_tuple(adaptadores…));
auto adaptadores_restantes = std::tuple_element_t<0, decltype(std::forward_as_tuple(adaptadores…))>{std::get<1>(std::forward_as_tuple(adaptadores…)), std::get<2>(std::forward_as_tuple(adaptadores…))…};
return apply_range_adaptors(std::forward
}
}
En este ejemplo, comenzamos con un rango
iota
de 0 a 9. Luego, aplicamos dos adaptadores utilizando la funciónapply_range_adaptors
:filter
para mantener solo los números pares ytransform
para elevar al cuadrado cada número. El resultado final es un rango que contiene los cuadrados de los números pares del 0 al 8.