Back to C++
2026-01-136 min read

Ranges library (C++)

Learn Ranges library (C++) step by step with clear examples and exercises.

Why This Matters

The Ranges library is an essential addition to C++ since version 20, offering a streamlined and flexible approach to handling data structures. By understanding the Ranges library, you can write cleaner, more efficient code, especially when dealing with complex data structures or performing operations that require multiple passes over a sequence. This knowledge is valuable for coding interviews, real-world projects, and debugging common issues in your programs.

Prerequisites

To make the most of this lesson, you should be familiar with:

  • Basic C++ syntax and concepts, such as variables, functions, loops, and control structures
  • Data structures like arrays, vectors, lists, and custom iterators
  • The Standard Template Library (STL) and its algorithms, such as std::sort and std::find

Core Concept

The Ranges library introduces the concept of _range_, which is a sequence of elements that can be accessed using begin() and end() functions. This abstraction simplifies the process of writing range-based algorithms by providing a unified interface for various data structures like arrays, vectors, lists, and even custom iterators.

Ranges Library Namespaces (C++)

The Ranges library is defined in the ` header file and resides within the std::ranges` namespace. To use it, you need to include this header at the beginning of your C++ source files:

#include <ranges>

Range Access Functions (C++)

The Ranges library provides several functions for accessing and manipulating ranges:

  1. begin(range): Returns an iterator pointing to the first element of the range.
  2. end(range): Returns an iterator pointing one past the last element of the range.
  3. cbegin(range): Returns a const iterator pointing to the first element of the range (for constant ranges).
  4. cend(range): Returns a const iterator pointing one past the last element of the range (for constant ranges).
  5. rbegin(range): Returns a reverse iterator pointing to the last element of the range (for bidirectional and random access ranges).
  6. rend(range): Returns a reverse iterator pointing one before the first element of the range (for bidirectional and random access ranges).
  7. size(range): Returns the number of elements in the range.
  8. data(range): Returns a pointer to the first element of the range (useful for contiguous ranges like arrays).
  9. reserve_hint(range, n): Provides a hint to the implementation about the expected size of the range (C++26).
  10. empty(range): Checks if the range is empty.

Range Conversions and Dangling Iterators (C++)

The Ranges library offers two types for handling ranges and dangling iterators:

  1. std::from_range_t: A type trait that determines whether a given type T can be used as a range (C++23).
  2. std::from_range(range): Converts a range into an object of type std::from_range_t.
  3. dangling borrowed_iterator_t: A type representing a dangling iterator, which may point beyond the end of its associated range (C++20).
  4. borrowed_subrange_t: Represents a subrange that is not owned by the object containing it (C++20).

Range Primitives and Concepts (C++)

The Ranges library also introduces several range primitives and concepts to help with creating custom ranges and algorithms:

  1. range_size_t: The type representing the size of a range.
  2. range_difference_t: The type representing the difference between two elements in a range.
  3. range_value_t: The type representing the value type of a range (C++23).
  4. elements_of(range): Returns an iterator pointing to the first element of the range.
  5. iterator_t, const_iterator_t, sentinel_t, and const_sentinel_t (C++23): Types representing iterators, sentinels, and const iterators for a given range type T.
  6. range_reference_t, range_const_reference_t, range_rvalue_reference_t, range_common_reference_t (C++23): Types representing reference types for a given range type T.
  7. Range concepts: range, borrowed_range, common_range, sized_range, viewable_range, input_range, output_range, forward_range, bidirectional_range, random_access_range, contiguous_range, approximately_sized_range (C++26), and constant_range (C++23).

Range Views (C++)

The Ranges library offers several range views that allow you to create new ranges based on existing ones:

  1. views::empty: A view representing an empty range.
  2. views::single: A view representing a single element of type T.
  3. views::istream: A view representing the contents of an input stream (C++ Standard Library streams).
  4. views::iota_view: A view that generates a sequence of integers from a start value to an end value, with a specified step (C++20).
  5. views::indices(range): A view that generates a sequence of indices for the elements in a given range.
  6. views::repeat(n): A view that repeats a given element n times (C++23).
  7. Range adaptors: views::all_t, views::as_rvalue_view, views::filter, views::transform, views::take_view, views::take_while_view, views::common_view, views::counted, views::as_input_view, views::drop_view, views::drop_while_view, views::lazy_split_view, views::split, views::join_view, views::join_with_view (C++23), and views::concat (C++26).
  8. views::cache_latest: A view that caches the latest value emitted by the underlying range (C++26).

Worked Example

Let's create a simple program using the Ranges library to sort an array of integers and print their sum:

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

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

// Sort the vector using the ranges library sort algorithm
std::sort(std::ranges::begin(numbers), std::ranges::end(numbers));

int sum = 0;
for (const auto& number : numbers | std::views::as_input_view) {
sum += number;
}

// Print the sorted array and its sum
std::cout << "Sorted numbers: ";
std::ranges::copy(numbers, std::ostream_iterator<int>(std::cout, ", "));
std::cout << "\nSum: " << sum << '\n';

return 0;
}

Common Mistakes

  1. Forgetting to include the `` header.
  2. Using the old-style iterators (like std::vector::iterator) instead of the new range-based iterators (like auto it = std::ranges::begin(numbers);).
  3. Not understanding the difference between a range and an iterator, leading to incorrect usage of begin()/end() functions or range concepts.
  4. Using dangling iterators without proper handling, which can lead to undefined behavior.
  5. Failing to include necessary header files (like `` for sorting) when using the Ranges library algorithms.
  6. Incorrectly implementing custom ranges or views, leading to compile errors or unexpected behavior.

Practice Questions

  1. Write a program that uses the Ranges library to find the second-largest number in an array of integers.
  2. Implement a custom range adaptor called MyFilterView that filters out even numbers from a given input range.
  3. Create a simple program using the Ranges library to reverse the order of elements in a string.
  4. Write a program that uses the Ranges library to find all pairs of integers in an array whose sum is equal to a given target value.
  5. Implement a custom range called MySortedRange that maintains its elements in sorted order, even when modified.

FAQ

Q: Can I use the Ranges library with older versions of C++?

A: No, the Ranges library is available only from C++20 onwards.

Q: How can I use the Ranges library with custom data structures like linked lists or trees?

A: You can create custom iterators for your data structure and make it compatible with the range concepts (range, bidirectional_range, etc.) to use the Ranges library algorithms.

Q: What happens if I try to use the Ranges library functions on a non-range object?

A: Compile errors will occur, as the Ranges library functions are designed to work only with range objects.

Q: Can I mix and match the old-style iterators and new-style range-based iterators in my code?

A: Yes, but it is generally recommended to use the new-style iterators for better compatibility with the Ranges library algorithms.

Q: What are some benefits of using the Ranges library over traditional C++ programming techniques?

A: The Ranges library simplifies common programming tasks by providing a unified interface for various data structures, reducing code duplication and improving readability. It also allows for more efficient range-based algorithms due to better optimization opportunities.

Ranges library (C++) | C++ | XQA Learn