C++20stladvanced
std::views::iota / empty / single (factory adaptors) (C++20 Addition)
C++20 · The Big Four · Compiler flag: -std=c++20
Explanation
Factory adaptors that generate ranges from scratch rather than adapting existing ones. `iota` produces incrementing sequences, `empty` produces zero-element ranges, and `single` produces one-element ranges. These serve as source nodes in pipelines.
Real-World Scenario
Generate test data or placeholder ranges in unit tests without creating actual containers.
Quick Snippet
snippet.cpp
#include <ranges>
// Generate indices
auto indices = std::views::iota(0, 100);
// Compose: even numbers from 0 to 98
auto evens = std::views::iota(0, 100)
| std::views::filter([](int n) { return n % 2 == 0; });
// Default empty result
auto no_data = std::views::empty<int>;Full Example
ranges_adaptor_factories.cpp
// CodeNebula - C++20 Example: views::iota, views::empty, views::single
// Compile: g++ -std=c++20 -Wall -Wextra -o example ranges_adaptor_factories.cpp
#include <iostream>
#include <ranges>
#include <vector>
#include <string>
int main() {
// views::iota - generate incrementing sequence
std::cout << "Bounded iota [1, 11): ";
for (int n : std::views::iota(1, 11)) std::cout << n << " ";
std::cout << "\n";
// Unbounded iota with take
std::cout << "Unbounded iota from 100 (first 5): ";
for (int n : std::views::iota(100) | std::views::take(5)) std::cout << n << " ";
std::cout << "\n";
// Iota for generating indices
std::vector<std::string> fruits = {"apple", "banana", "cherry", "date"};
std::cout << "\nIndexed fruits:\n";
for (int i : std::views::iota(0, static_cast<int>(fruits.size())))
std::cout << " " << i << ": " << fruits[i] << "\n";
// views::empty - a range with no elements
std::cout << "Empty view size: " << std::ranges::size(std::views::empty<int>) << "\n";
int count = 0;
for ([[maybe_unused]] int n : std::views::empty<int>) ++count;
std::cout << "Elements iterated in empty: " << count << "\n";
// views::single - a range with exactly one element
std::cout << "\nSingle(42): ";
for (int n : std::views::single(42)) std::cout << n << " ";
std::cout << "\n";
auto sv = std::views::single(std::string("hello"));
std::cout << "Single string: " << *sv.begin() << "\n";
// Combining factories with adaptors
std::cout << "\nIota squares (first 8): ";
for (int n : std::views::iota(1)
| std::views::transform([](int x) { return x * x; })
| std::views::take(8))
std::cout << n << " ";
std::cout << "\n";
// Iota with filter: prime numbers
auto is_prime = [](int n) {
if (n < 2) return false;
for (int i = 2; i * i <= n; ++i)
if (n % i == 0) return false;
return true;
};
std::cout << "First 10 primes: ";
for (int n : std::views::iota(2)
| std::views::filter(is_prime)
| std::views::take(10))
std::cout << n << " ";
std::cout << "\n";
// Using factories for generic code patterns
auto process = [](auto rng) {
int sum = 0;
for (int n : rng) sum += n;
return sum;
};
std::cout << "\nSum of iota(1,6): " << process(std::views::iota(1, 6)) << "\n";
std::cout << "Sum of single(99): " << process(std::views::single(99)) << "\n";
std::cout << "Sum of empty: " << process(std::views::empty<int>) << "\n";
return 0;
}
Run command
g++ -std=c++20 -Wall -Wextra -o example ranges_adaptor_factories.cpp