LibraryRanges

Ranges

Learn about Ranges as part of C++ Modern Systems Programming and Performance

Introduction to C++ Ranges

C++20 introduced Ranges, a powerful feature that revolutionizes how we work with sequences of elements. Ranges provide a more expressive, composable, and efficient way to process data compared to traditional iterator-based algorithms.

What are Ranges?

At its core, a range is simply a pair of iterators: a beginning iterator and an ending iterator. However, the C++ Ranges library provides a rich set of utilities and adaptors that allow you to chain operations on these ranges in a fluent and readable manner. This enables a more functional programming style within C++.

Ranges simplify sequence operations by chaining adaptors.

Instead of writing complex loops or nested algorithm calls, you can chain operations like filtering, transforming, and taking elements from a range.

Consider a common task: filtering a collection of numbers, then transforming them, and finally taking the first few. With traditional C++, this might involve multiple loops or algorithm calls with intermediate storage. With ranges, you can express this as a single, declarative pipeline.

Key Concepts and Components

The Ranges library is built around several key concepts:

  • Range: An object that can be iterated over, typically defined by a begin and end iterator.
  • View: A range adaptor that transforms or filters an existing range without copying elements. Views are lazy, meaning operations are performed only when elements are accessed.
  • Adaptor: Functions that take a range and return a new range (often a view) with modified behavior (e.g.,
    code
    filter
    ,
    code
    transform
    ,
    code
    take
    ).
  • Pipeline: The composition of multiple range adaptors, forming a chain of operations.

Common Range Adaptors

AdaptorDescriptionExample Usage
views::filterFilters elements based on a predicate.my_range | views::filter([](int x){ return x % 2 == 0; })
views::transformApplies a function to each element.my_range | views::transform([](int x){ return x * 2; })
views::takeTakes a specified number of elements from the beginning.my_range | views::take(5)
views::dropDrops a specified number of elements from the beginning.my_range | views::drop(3)
views::reverseReverses the order of elements.my_range | views::reverse

Benefits of Using Ranges

Ranges offer significant advantages for modern C++ development:

  • Readability: Code becomes more declarative and easier to understand, resembling mathematical notation.
  • Composability: Adaptors can be chained together to build complex operations from simpler ones.
  • Efficiency: Views are lazy and often avoid unnecessary intermediate copies, leading to better performance.
  • Safety: Reduces the risk of off-by-one errors common with manual iterator management.

Think of ranges as a data processing pipeline. Data flows through a series of transformations, each step building upon the previous one, without needing to materialize intermediate results.

Example: Filtering and Transforming

Let's see a practical example. Suppose we have a vector of integers and we want to get the squares of all even numbers, taking only the first three results.

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

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

    auto processed_range = numbers
                       | std::views::filter([](int n){ return n % 2 == 0; })
                       | std::views::transform([](int n){ return n * n; })
                       | std::views::take(3);

    for (int val : processed_range) {
        std::cout << val << " ";
    }
    std::cout << std::endl;
    // Output: 4 16 36
}

This code demonstrates a pipeline: first, it filters for even numbers, then it transforms each even number by squaring it, and finally, it takes the first three results from this processed sequence. The | operator is used to chain these operations.

📚

Text-based content

Library pages focus on text content

Getting Started with Ranges

To use C++20 Ranges, ensure your compiler supports C++20 and include the

code
header. Familiarize yourself with the common views and adaptors. Experiment with simple pipelines to build your understanding.

What is the primary benefit of using C++20 Ranges over traditional iterator-based algorithms for sequence processing?

Improved readability, composability, efficiency (due to lazy evaluation and reduced intermediate copies), and safety.

What does a C++ Range View do?

A view is a range adaptor that transforms or filters an existing range without copying elements, and operations are performed lazily when elements are accessed.

Learning Resources

C++20 Ranges - cppreference.com(documentation)

The official and most comprehensive documentation for the C++20 Ranges library, detailing all views, actions, and concepts.

A Tour of C++: Ranges(documentation)

Bjarne Stroustrup's concise overview of C++20 features, including a section dedicated to explaining the core ideas behind ranges.

C++20 Ranges: A Deep Dive(video)

A detailed video tutorial explaining the concepts, benefits, and practical usage of C++20 Ranges with code examples.

Understanding C++20 Ranges(blog)

An insightful blog post that breaks down the fundamental concepts of C++20 Ranges and provides clear examples of their application.

Range-v3 Library: The Foundation for C++20 Ranges(documentation)

Explore the range-v3 library, which heavily influenced the standard C++20 Ranges, offering a preview and deeper understanding of its design.

C++20 Ranges: The Missing Piece?(video)

A presentation discussing the impact and advantages of C++20 Ranges in modern C++ programming, highlighting its expressive power.

Practical C++20 Ranges: Examples and Use Cases(blog)

This article focuses on practical examples and common use cases for C++20 Ranges, making it easier to integrate them into your projects.

C++20 Ranges Explained(video)

A clear and concise explanation of C++20 Ranges, covering the core ideas and how to start using them effectively.

The C++ Standard Library: Ranges(documentation)

An alternative reference for the C++ Standard Library, including detailed information on the ranges facilities.

C++20 Ranges: A Functional Approach to Data Processing(blog)

This article delves into the functional programming aspects of C++20 Ranges and how they enable a more declarative style of coding.