etl/docs/ranges/ranges.md
Roland Reichwein c6c1ee1b28
Add missing etl::ranges::distance overload (#1569)
* Update _index.md

* Update _index.md

* Cherry pick the Docker fixes for PowerPC (#1563)

Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>

* Add missing etl::ranges::distance overload

---------

Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
2026-08-26 20:16:54 +01:00

16 KiB
Raw Permalink Blame History

title weight
Ranges 1

{{< callout >}} Header: ranges.h
Since: 20.46.2
Similar to: std::ranges {{< /callout >}}

ETL C++17 Ranges Implementation

Overview

The Embedded Template Library provides a C++17-compatible implementation of ranges, inspired by the C++20 ranges library. This implementation enables range-based algorithms and views for embedded and resource-constrained environments where full C++20 support may not be available.

Features

  • Ranges: Provides range types and iterator wrappers for composing operations over sequences.
  • Views: Includes lightweight, composable views such as filter_view, transform_view, and subrange.
  • Algorithms: Supports range-based algorithms compatible with ETL containers and standard containers.
  • Compatibility: Designed for C++17, with minimal dependencies and no reliance on C++20 features.

Getting Started

Include the main header in your project:

#include <etl/ranges.h>

Example Usage

Using Ranges

#include <etl/print.h>
#include <etl/ranges.h>
#include <etl/vector.h>

...

  etl::vector<int, 10> data = {6, 1, 3, 3, 2};
  etl::ranges::sort(data);
  etl::ranges::for_each(data, [](const int& i){etl::print(" {}", i);});

Output:

 1 2 3 3 6

Using Views

#include <etl/print.h>
#include <etl/ranges.h>
#include <etl/vector.h>

...

  etl::vector<int, 10> data = {1, 2, 3, 4, 5};
  auto even = [](int v) { return v % 2 == 0; };
  auto filtered = etl::ranges::filter_view(data, even);
  etl::ranges::for_each(filtered, [](const int& i){etl::print(" {}", i);});

Output:

 2 4

Transforming Elements

#include <etl/print.h>
#include <etl/ranges.h>
#include <etl/vector.h>

...

  etl::vector<int, 10> data = {1, 2, 3, 4, 5};
  auto squared = etl::ranges::transform_view(data, [](int v) { return v * v; });
  etl::ranges::for_each(squared, [](const int& i){etl::print(" {}", i);});

Output:

 1 4 9 16 25

Composition

Views can be composed using the pipe (|) operator, allowing you to chain multiple transformations in a readable, left-to-right style:

#include <etl/print.h>
#include <etl/ranges.h>
#include <etl/vector.h>

namespace views = etl::ranges::views;

...

  etl::vector<int, 10> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

  auto result = data
    | views::filter([](const int& v) { return v % 2 == 0; })
    | views::transform([](const int& v) { return v * v; });

  etl::ranges::for_each(result, [](const int& i){ etl::print(" {}", i); });

Output:

 4 16 36 64 100

This first filters the even numbers and then squares them. Each | passes the result of the previous stage as input to the next view adaptor.

Range Access and Primitives

These are declared in the etl::ranges namespace in iterator.h, which is included by ranges.h.

Range access

Function objects, equivalent to their std::ranges counterparts.

Name Description
begin, end The iterator to the first element, and the sentinel.
cbegin, cend The const iterator to the first element, and the const sentinel.
rbegin, rend The reverse iterator to the last element in forward order, and the past-the-end reverse iterator.
crbegin, crend The const reverse iterator to the last element in forward order, and the const past-the-end reverse iterator.
size The number of elements, as a size_t.
ssize The number of elements, as a ptrdiff_t.
empty Whether the range has no elements.
data, cdata A pointer to the first element.
distance The number of elements between two iterators, or in a range.
advance Advances an iterator by a given distance and/or to a bound.
next, prev An iterator advanced forwards or backwards by a given distance and/or to a bound.

size and ssize use the range's size() member if it has one; otherwise they count the elements by traversing the range, which requires at least a forward range.

distance

// Iterator and sentinel of the same type.
template <typename I>
constexpr etl::iter_difference_t<I> distance(I first, I last)

// Iterator and sentinel of different types.
template <typename I, typename S>
constexpr etl::iter_difference_t<I> distance(I first, S last)

// Range.
template <typename R>
constexpr etl::iter_difference_t<etl::ranges::iterator_t<R>> distance(R&& r)

The range overload uses the range's size() member if it has one; otherwise it counts the elements by traversing from begin() to end().

Range primitives

Alias templates that give the associated types of a range.

Name Description
iterator_t<R> The iterator type.
const_iterator_t<R> The const iterator type.
sentinel_t<R> The sentinel type.
const_sentinel_t<R> The const sentinel type.
range_size_t<R> The size type.
range_difference_t<R> The difference type.
range_value_t<R> The element value type.
range_reference_t<R> The element reference type.

Supported Views

All views are in the etl::ranges namespace. Corresponding range adaptor objects are available in etl::ranges::views.

Range Factories

View views:: adaptor Description
empty_view<T> views::empty<T> A view with no elements.
single_view views::single A view containing exactly one element.
iota_view views::iota A view of sequentially increasing values.
repeat_view views::repeat A view that repeats a value a given number of times.

Range Adaptors

View views:: adaptor Description
ref_view views::ref A non-owning view that wraps a reference to a range.
owning_view views::owning A view that takes ownership of a range via move.
— views::all Returns the range itself (if already a view), a ref_view, or an owning_view.
filter_view views::filter Filters elements based on a predicate.
transform_view views::transform Applies a transformation to each element.
as_rvalue_view views::as_rvalue Casts each element to an rvalue reference.
as_const_view views::as_const Provides a const view of the elements.
cache_latest_view views::cache_latest Caches the most recently accessed element (avoids recomputation).
reverse_view views::reverse Reverses the order of elements.
drop_view views::drop Skips the first n elements.
drop_while_view views::drop_while Skips leading elements while a predicate is true.
take_view views::take Takes the first n elements.
take_while_view views::take_while Takes leading elements while a predicate is true.
join_view views::join Flattens a range of ranges into a single range.
join_with_view views::join_with Flattens a range of ranges, inserting a delimiter between each.
split_view views::split Splits a range into subranges around a delimiter pattern.
lazy_split_view views::lazy_split Lazily splits a range by a pattern (inner ranges discovered on iteration).
— views::counted Creates a view of n elements starting from an iterator.
concat_view views::concat Concatenates multiple ranges into a single view.
zip_view views::zip Zips multiple ranges into a view of tuples (length of shortest range).
zip_transform_view views::zip_transform Zips multiple ranges and applies a function to each tuple of elements.
common_view views::common Adapts a view so that its iterator and sentinel types are the same.
enumerate_view views::enumerate Pairs each element with its index, producing tuples of (index, value).
elements_view views::elements Extracts the N-th element from each tuple-like value.
keys_view views::keys Alias for elements_view with N=0 (extracts first element of pairs/tuples).
values_view views::values Alias for elements_view with N=1 (extracts second element of pairs/tuples).
adjacent_view views::adjacent Produces a view of tuples of N adjacent elements (sliding window of tuples).
— views::pairwise Alias for views::adjacent<2>.
adjacent_transform_view views::adjacent_transform Applies a function to each group of N adjacent elements.
— views::pairwise_transform Alias for views::adjacent_transform<2>.
chunk_view views::chunk Splits a range into non-overlapping chunks of a given size.
slide_view views::slide Produces overlapping subranges (sliding windows) of a given size.
chunk_by_view views::chunk_by Splits a range into subranges between adjacent elements where a predicate is false.
stride_view views::stride Yields every N-th element from the underlying range.
cartesian_product_view views::cartesian_product Produces the Cartesian product of multiple ranges as a view of tuples.
to_input_view views::to_input Downgrades iterator category to input iterator while preserving elements and order.
subrange — Represents a sub-range defined by an iterator–sentinel pair.

All views support range-based for-loop iteration and can be composed with the pipe (|) operator.

Supported Algorithms

All algorithms are callable objects in the etl::ranges namespace. Each supports both an iterator-pair overload and a range overload (where applicable), and most accept optional projection and comparator arguments.

Non-modifying Sequence Operations

Algorithm Description
for_each Applies a function to each element in a range.
for_each_n Applies a function to the first n elements.
find Finds the first element equal to a value.
find_if Finds the first element satisfying a predicate.
find_if_not Finds the first element not satisfying a predicate.
find_end Finds the last occurrence of a subsequence.
find_first_of Finds the first element matching any in a second range.
adjacent_find Finds the first pair of adjacent equal elements.
count Counts elements equal to a value.
count_if Counts elements satisfying a predicate.
all_of Checks if all elements satisfy a predicate.
any_of Checks if any element satisfies a predicate.
none_of Checks if no elements satisfy a predicate.
mismatch Finds the first position where two ranges differ.
equal Checks if two ranges are equal.
is_permutation Checks if one range is a permutation of another.
search Searches for the first occurrence of a subsequence.
search_n Searches for n consecutive copies of a value.
starts_with Checks if a range starts with another range.
ends_with Checks if a range ends with another range.
lexicographical_compare Compares two ranges lexicographically.

Fold Operations

Algorithm Description
fold_left Left-folds elements with a binary operation.
fold_left_with_iter Left-folds, returning both the result and an iterator.
fold_left_first Left-folds using the first element as the initial value.
fold_left_first_with_iter Like fold_left_first, also returning an iterator.
fold_right Right-folds elements with a binary operation.
fold_right_last Right-folds using the last element as the initial value.

Modifying Sequence Operations

Algorithm Description
copy Copies elements to a destination range.
copy_n Copies n elements to a destination range.
copy_if Copies elements satisfying a predicate.
copy_backward Copies elements backwards to a destination range.
move Moves elements to a destination range.
move_backward Moves elements backwards to a destination range.
swap_ranges Swaps elements between two ranges.
replace Replaces elements equal to a value.
replace_if Replaces elements satisfying a predicate.
replace_copy Copies, replacing elements equal to a value.
replace_copy_if Copies, replacing elements satisfying a predicate.
remove Removes elements equal to a value.
remove_if Removes elements satisfying a predicate.
remove_copy Copies, omitting elements equal to a value.
fill Fills a range with a value.
fill_n Fills n elements with a value.
generate Assigns each element the result of a generator function.
generate_n Assigns n elements the result of a generator function.
iota Fills a range with sequentially increasing values.
unique Removes consecutive duplicate elements.
unique_copy Copies, removing consecutive duplicates.
transform Applies a transformation to each element.
reverse Reverses the order of elements.
reverse_copy Copies elements in reverse order.
rotate Rotates elements in a range.
rotate_copy Copies elements with rotation.
shift_left Shifts elements to the left.
shift_right Shifts elements to the right.
shuffle Randomly reorders elements.
sample Selects n random elements from a range.

Sorting Operations

Algorithm Description
sort Sorts elements in a range.
stable_sort Sorts elements preserving relative order of equivalent elements.
partial_sort Partially sorts a range so that the first n elements are sorted.
partial_sort_copy Copies and partially sorts elements.
nth_element Partially sorts so that the n-th element is in its sorted position.
is_sorted Checks if a range is sorted.
is_sorted_until Finds the first unsorted element.

Partitioning Operations

Algorithm Description
partition Partitions elements by a predicate.
stable_partition Partitions elements, preserving relative order.
is_partitioned Checks if a range is partitioned.
partition_copy Copies elements into two ranges based on a predicate.
partition_point Finds the partition point.

Binary Search (on sorted ranges)

Algorithm Description
lower_bound Finds the first element not less than a value.
upper_bound Finds the first element greater than a value.
equal_range Returns the range of elements equal to a value.
binary_search Checks if a sorted range contains a value.

Set Operations (on sorted ranges)

Algorithm Description
includes Checks if one sorted range includes another.
merge Merges two sorted ranges.
inplace_merge Merges two consecutive sorted sub-ranges in place.
set_union Computes the union of two sorted ranges.
set_intersection Computes the intersection of two sorted ranges.
set_difference Computes the difference of two sorted ranges.
set_symmetric_difference Computes the symmetric difference of two sorted ranges.

Heap Operations

Algorithm Description
make_heap Creates a heap from a range.
push_heap Pushes an element onto a heap.
pop_heap Pops the top element from a heap.
sort_heap Sorts a heap into a sorted range.
is_heap Checks if a range is a heap.
is_heap_until Finds the first element that breaks the heap property.

Min/Max Operations

Algorithm Description
min Returns the smaller of two values or the smallest in an initializer list.
min_element Finds the smallest element in a range.
max Returns the larger of two values or the largest in an initializer list.
max_element Finds the largest element in a range.
minmax Returns the smaller and larger of two values.
minmax_element Finds both the smallest and largest elements in a range.
clamp Clamps a value between a minimum and maximum.

Permutation Operations

Algorithm Description
next_permutation Generates the next lexicographic permutation.
prev_permutation Generates the previous lexicographic permutation.

Reference

For reference to the STD implementation, see also:

Limitations

  • Not all C++20 range features are available due to limitation to C++17. Especially C++20 concepts are not used.
  • Designed for ETL containers but can work with standard containers if compatible with ETL's iterator requirements.