Saltar a contenido

Última actualización:2026-10-12

La biblioteca Ranges de C++20

ranges es una de las características principales de C++20, y los "view" son una parte bastante importante de ella. Antes de C++20, los algoritmos de la biblioteca estándar se implementaban sobre iteradores, por ejemplo: std::sort.

std::sort(v.begin() + 2, v.end())

Iteradores + algoritmos permiten completar algunas operaciones complejas; por ejemplo, si quiero ordenar en sentido inverso:

std::sort(v.rbegin(), v.rend())

Pero esto también acarrea algunos problemas:

  • Es fácil mezclar dos iteradores incompatibles.
  • La capacidad de composición de los algoritmos es demasiado débil y obliga a almacenar variables intermedias

Por ejemplo: supongamos un sistema de información de estudiantes y que queremos calcular la suma de las GPA de los estudiantes cuya edad está en el intervalo 21-25 y con GPA >= 3.5. Antes de C++17 podríamos escribir un pseudocódigo como este:

std::vector<Student> students
std::vector<Student> selected;
std::copy_if(students.begin(), students.end(), std::back_inserter(selected),
             [](const Student& student) {
               return student.age >= 21 && student.age <= 25 && student.gpa >= 3.5;
             });

double s = std::accumulate(
    selected.begin(), selected.end(), 0.0,
    [](double sum, const Student& student) { return sum + student.gpa; });

Se ve que, al filtrar la información de los estudiantes que cumplen las condiciones, hay que copiarla a selected y luego sumar.

C++20 introduce una forma de escribirlo más concisa y eficiente: usando rangos y el operador de tubería | para encadenar varias operaciones, se puede sumar directamente sin variables intermedias; por ejemplo:

double s = 0.0;
for (const auto& student :
     students | std::views::filter([](const auto& s) {
       return s.age >= 21 && s.age <= 25 && s.gpa >= 3.5;
     }) | std::views::transform([](const auto& s) { return s.gpa; })) {
  s += student;
}

Se ve que varios algoritmos se encadenan sin costuras, reduciendo las asignaciones de memoria de las variables temporales intermedias; la legibilidad también aumenta notablemente, conectando las distintas manipulaciones mediante la tubería |.

A continuación, exploremos juntos los contenidos relacionados con los ranges de C++20.

1.Conceptos básicos

1.range

Un range es un concepto abstracto que representa una secuencia. Puede ser cualquier contenedor con iteradores, o un objeto que defina las funciones begin() y end(). std::vector, std::list, etc., son ejemplos de rangos. Los arrays también pueden considerarse rangos.

2.view

Un view es un acceso de solo lectura a un Range. Es una forma de evaluación perezosa: solo calcula cuando se necesita, lo que significa que no almacena datos realmente. Por ejemplo: std::views::filter y std::views::transform son ejemplos típicos de view. Nos permiten filtrar y transformar un range sin crear realmente contenedores nuevos.

3.algorithm

Los algoritmos son funciones que operan sobre un range o un view; por ejemplo, std::sort, std::find, etc., son ejemplos de algoritmos.

4.|

El operador de tubería | permite encadenar vistas y algoritmos, tomando el resultado del lado izquierdo como entrada del lado derecho. Hace el código más claro y conciso. Por ejemplo: students | std::views::filter(...) pasa el rango students a std::views::filter para la operación de filtrado, y luego pasa el resultado a las operaciones siguientes.

Tomando como ejemplo el cálculo con students de arriba: en ese ejemplo usamos el rango students como entrada de la vista filter mediante |, luego el resultado como entrada de la vista transform, y al final obtenemos un rango sobre el que iteramos, sumando mediante un algoritmo de acumulación para obtener el resultado.

double s = 0.0;
for (const auto& student :
     students | std::views::filter([](const auto& s) {
       return s.age >= 21 && s.age <= 25 && s.gpa >= 3.5;
     }) | std::views::transform([](const auto& s) { return s.gpa; })) {
  s += student;
}

Como puede verse, usar ranges tiene las ventajas siguientes:

  • Mejora la legibilidad del código
  • Evaluación perezosa: Ranges introduce el concepto de vista (view), que permite la evaluación perezosa, es decir, calcular el resultado solo cuando se necesita.

Por ejemplo: solo se calcula al hacer *v.begin().

auto v = std::views::reverse(vec);
std::cout << *v.begin() << std::endl;
  • Menos errores: el diseño de Ranges ayuda a reducir algunos errores habituales en las operaciones tradicionales con iteradores, como usar iteradores incompatibles.
  • Etcétera.

El concepto de rango introduce distintos conceptos para describir diferentes tipos de rangos. Estos conceptos ayudan a comprender y restringir mejor las propiedades de los rangos en programación genérica. Estos son algunos conceptos de rango de uso frecuente:

https://en.cppreference.com/w/cpp/ranges

Concepto Descripción Ejemplos de contenedores
std::ranges::input_range Se puede iterar al menos una vez de principio a fin std::forward_list、std::list、std::duque、std::array、std::vector
std::ranges::forward_range Se puede iterar varias veces de principio a fin std::forward_list、std::list、std::duque、std::array、std::vector
std::ranges::bidirectional_range Los iteradores también pueden desplazarse hacia atrás con -- std::list、std::duque、std::array、std::vector
std::ranges::random_access_range Puedes saltar a un elemento [] en tiempo constante std::duque、std::array、std::vector
std::ranges::contiguous_range Los elementos siempre se almacenan de forma contigua en memoria std::array、std::vector

2.Uso

Usar esta característica es bastante sencillo: basta con incluir el archivo de cabecera y usar la interfaz.

Por ejemplo: filtrar los números pares de un conjunto de números.

#include <ranges>
auto evenNumbers = numbers | std::views::filter([](int x) { return x % 2 == 0; });

Compilación: basta con especificar -std.

g++ -std=c++20 main.cc -o main

Sobre el soporte de los compiladores puede consultarse la siguiente lista:

https://en.cppreference.com/w/cpp/compiler_support/20

gcc >=10, clang >=13 (parcial), >=15 soporte completo.

Temas relacionados

Comentarios