How to Use std::views::chunk in C++

Introduced in C++23, std::views::chunk is a standard range adaptor that divides an input sequence into non-overlapping, contiguous sub-ranges of a specified maximum size. This article explains the mechanics of how std::views::chunk segments consecutive elements into fixed-size views, demonstrates how to implement it in modern C++ code, and details how it handles uneven sequences and range categories.

Understanding std::views::chunk

std::views::chunk takes two arguments: an input range and an integer N representing the chunk size. It produces a range of ranges, where each inner range represents a chunk of up to N consecutive elements from the source.

Like most range adaptors in the <ranges> header, std::views::chunk operates lazily. It does not allocate new containers or copy elements; instead, it generates sub-ranges on demand as the outer range is iterated.

Basic Syntax and Usage

You can invoke std::views::chunk either as a functional call or using the pipe operator (|):

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

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

    // Group elements into chunks of 3
    for (auto chunk : numbers | std::views::chunk(3)) {
        std::cout << "[ ";
        for (int n : chunk) {
            std::cout << n << " ";
        }
        std::cout << "]\n";
    }

    return 0;
}

Output:

[ 1 2 3 ]
[ 4 5 6 ]
[ 7 8 ]

Handling Remaining Elements

If the total number of elements in the source range is not evenly divisible by N, the final chunk simply contains all remaining elements. It will have a size strictly less than N, and no padding, exceptions, or undefined behavior occur. When the source range is empty, the adaptor yields an empty range of chunks.

How Chunking Works Under the Hood

The underlying type produced by this view is std::ranges::chunk_view. Its implementation adapts based on the iterator concepts supported by the source range:

  1. Forward and Random-Access Ranges: If the underlying range models at least std::ranges::forward_range, iterators can be saved and traversed independently. When accessing a chunk, the view calculates the sub-range using iterator arithmetic (such as std::ranges::next(current, N, end)). If the source range is sized and random-access, the chunks themselves can provide random-access semantics and constant-time size queries.
  2. Input Ranges: If the source range is an input-only range (such as reading from an input stream), elements cannot be revisited. In this case, chunk_view manages an internal counter and caches the current position so that advancing through an inner chunk advances the parent input stream sequentially.

Key Considerations

  • Chunk Size Validation: The specified chunk size N must be greater than zero. Passing a value less than or equal to zero leads to undefined behavior.
  • Element Lifetime: Because std::views::chunk creates non-owning views over the original data, the underlying container must outlive the view to prevent dangling references.
  • Composability: As part of the standard ranges library, std::views::chunk can be seamlessly chained with other adaptors, such as std::views::filter, std::views::transform, or std::views::reverse.