Understanding std::views::elements in C++
The std::views::elements adaptor in C++20 provides a
generic way to project a specific component out of a sequence of
tuple-like objects. This article explains what
std::views::elements extracts from collections of tuples or
pairs, demonstrates its syntax with compile-time indexing, and examines
its relationship with common utility views like
std::views::keys and std::views::values.
What
std::views::elements Extracts
The std::views::elements<N> range adaptor takes a
view of tuple-like elements (such as std::tuple,
std::pair, or std::array) and produces a new
view containing only the \(N\)-th
element of each entry. The index N is a zero-based
compile-time constant provided as a template argument.
For any element \(E\) in the source
range, std::views::elements<N> accesses the component
using the equivalent of std::get<N>(E).
Working with std::pair
When applied to a collection of std::pair objects,
std::views::elements extracts either the first or second
member based on the provided index:
std::views::elements<0>extracts thefirstmember of every pair.std::views::elements<1>extracts thesecondmember of every pair.
#include <iostream>
#include <vector>
#include <utility>
#include <ranges>
int main() {
std::vector<std::pair<int, std::string>> data = {
{1, "One"}, {2, "Two"}, {3, "Three"}
};
// Extract the second element (std::string)
for (const auto& name : data | std::views::elements<1>) {
std::cout << name << ' '; // Outputs: One Two Three
}
}Working with
std::tuple and Larger Structures
Unlike standard pair accessors, std::views::elements
generalizes to tuples and arrays of any size, allowing extraction of
arbitrary fields:
#include <iostream>
#include <vector>
#include <tuple>
#include <ranges>
int main() {
std::vector<std::tuple<int, std::string, double>> employees = {
{101, "Alice", 75000.0},
{102, "Bob", 82000.0},
{103, "Charlie", 68000.0}
};
// Extract the third element (double salary)
for (double salary : employees | std::views::elements<2>) {
std::cout << salary << ' '; // Outputs: 75000 82000 68000
}
}Attempting to access an index out of bounds (for instance,
std::views::elements<3> on a 3-element tuple) results
in a compile-time error.
Relationship to
keys and values
C++ provides dedicated aliases for the two most common use cases involving two-element structures:
std::views::keysis an alias forstd::views::elements<0>.std::views::valuesis an alias forstd::views::elements<1>.
These aliases are primarily used when iterating over associative
containers like std::map or
std::unordered_map, where the elements are stored as
std::pair<const Key, Value>.
Key Characteristics
- Lazy Evaluation:
std::views::elementsdoes not copy or store elements; it projects values on the fly during iteration. - Value Category Preservation: If the underlying range provides lvalue references, the view yields lvalue references, allowing in-place modification of non-const elements.
- Tuple-like Concept: The adaptor operates on any
type that models the internal tuple-like protocol, meaning it supports
std::tuple_size,std::tuple_element, andstd::get.