Skip to main content

C Plus Plus

What are Ranges in C++20 ?

C++20 introduced Ranges, a powerful standard library feature that simplifies code by replacing loops and iterators with a functional programming style for working with sequences.

C++20 introduced a new standard library feature called Ranges, which provides a powerful and expressive way to work with sequences of elements. Ranges simplify the code by replacing traditional loops and iterators with a functional programming style. They offer a wide range of operations for manipulating and transforming sequences, making code more concise, readable, and expressive.

Traditional Iterators vs. Ranges

In pre-C++20, iterating over a container or a sequence of elements involved using iterators and manually writing loops. This approach often led to verbose code, with iterators requiring explicit management and complex loop structures. Ranges aim to simplify this process by providing a higher-level abstraction for working with sequences.

Ranges allow you to express operations directly on sequences, without the need for explicit loops and iterator manipulation. They provide a unified and consistent syntax for a variety of operations, such as filtering, transforming, slicing, sorting, and more. Ranges operate lazily, meaning that they evaluate only as much as needed, improving performance by avoiding unnecessary computations.

Key Concepts in Ranges

To understand ranges in C++20, let's explore some key concepts:

1. Range

A range represents a sequence of elements. It can be any container, array, or even an infinite sequence. Ranges have a common set of operations that can be applied, making them highly composable.

2. View

A view is an object that provides a read-only representation of a range. Views are lightweight and do not modify the underlying data. They allow for chaining multiple operations together to form a pipeline of transformations on a range.

3. Algorithm

An algorithm is a function that operates on a range or a view. Algorithms perform operations such as sorting, searching, filtering, and transforming the elements of a range. They take one or more ranges/views as input and produce a result or perform side effects.

4. Pipe Operator (|)

The pipe operator (|) allows you to chain views and algorithms together, creating a concise and expressive syntax. It passes the result of the left-hand side as input to the right-hand side.

Example Usage of Ranges

To demonstrate the power and simplicity of ranges, let's look at an example:

#include <iostream>
#include <vector>
#include <ranges>

int main() {
  std::vector<int> numbers{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

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

  for (int x : evenNumbers) {
    std::cout << x << " ";
  }
  std::cout << std::endl;

  return 0;
}

In this code, we start with a vector of numbers and use the filter view from the std::views namespace to create a new view that only includes even numbers. We then iterate over this view using a range-based for loop and print each element.

This concise syntax eliminates the need for manual loops and if statements, making the code more readable and expressive.

To compile this program, you would use the following command:

g++ -std=c++20 ranges.cpp -o ranges

Benefits of Ranges

Ranges offer several benefits over traditional iterator-based approaches:

1. Improved Readability: Ranges provide a higher-level abstraction, resulting in more readable and expressive code. The operations can be chained together, making the code read like a series of transformations applied to a range.

2. Code Reusability: With ranges, you can create reusable views and algorithms that can be applied to different ranges or views. This promotes code reuse and modular design.

3. Lazy Evaluation: Ranges are evaluated lazily, meaning that computations are performed only when required. This can improve performance by avoiding unnecessary calculations.

4. Enhanced Expressiveness: Ranges enable a more functional programming style in C++. You can leverage lambdas and other functional constructs to express complex transformations succinctly.

Here are the code examples that demonstrate the usage of ranges in C++20, along with their corresponding outputs: