CodeNebula
C++20stladvanced

std::ranges::output_range (C++20 Addition)

C++20 · The Big Four · Compiler flag: -std=c++20

Explanation

Concept for ranges that support writing values of a specific type through their iterators. Parameterized on both the range type and the value type being written.

Real-World Scenario

Write processed results to an output buffer in a signal processing pipeline.

Quick Snippet

snippet.cpp
#include <ranges>

template<std::ranges::output_range<int> R>
void fill_with_zeros(R&& r) {
    for (auto&& elem : r) elem = 0;
}

Full Example

ranges_output_range.cpp
// CodeNebula - C++20 Example: std::ranges::output_range Concept
// Compile: g++ -std=c++20 -Wall -Wextra -o example ranges_output_range.cpp

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

// std::ranges::output_range<R, T> checks that a range's iterator
// can be used to write values of type T into the range.

// Fill an output range with a repeated value
template <typename T, std::ranges::output_range<T> R>
void fill_range(R&& r, const T& value) {
    for (auto it = std::ranges::begin(r); it != std::ranges::end(r); ++it) {
        *it = value;
    }
}

// Generate values into an output range using a function
template <typename R, typename Gen>
    requires std::ranges::output_range<R, std::invoke_result_t<Gen>>
void generate_into(R&& r, Gen gen) {
    for (auto it = std::ranges::begin(r); it != std::ranges::end(r); ++it) {
        *it = gen();
    }
}

int main() {
    // Vectors and lists are output ranges for their value type
    static_assert(std::ranges::output_range<std::vector<int>, int>);
    static_assert(std::ranges::output_range<std::list<double>, double>);

    // Fill a vector with a value
    std::vector<int> vec(5);
    fill_range(vec, 42);
    std::cout << "Filled vector: ";
    for (int v : vec) std::cout << v << " ";
    std::cout << "\n";

    // Generate sequential values
    std::vector<int> seq(8);
    int counter = 1;
    generate_into(seq, [&counter]() { return counter++; });
    std::cout << "Generated sequence: ";
    for (int v : seq) std::cout << v << " ";
    std::cout << "\n";

    // Using ranges::fill from the standard library
    std::list<std::string> words(4);
    std::ranges::fill(words, "hello");
    std::cout << "Filled list: ";
    for (const auto& w : words) std::cout << w << " ";
    std::cout << "\n";

    // A span is also an output range
    int arr[5] = {};
    auto sp = std::span(arr);
    static_assert(std::ranges::output_range<decltype(sp), int>);
    fill_range(sp, 99);
    std::cout << "Filled span: ";
    for (int v : arr) std::cout << v << " ";
    std::cout << "\n";

    return 0;
}
Run command
g++ -std=c++20 -Wall -Wextra -o example ranges_output_range.cpp