std::ranges::elements_of(3)
β¨ std::ranges::elements_of β¨
okay bestie, welcome to the std::ranges::elements_of page from the C++ Standard Libary (yes that's how the header spells it, don't come for me π
). this one's short and sweet and honestly kind of iconic once you get what it's for, so let's go π«Ά
πΈ NAME πΈ
std::ranges::elements_of β literally just std::ranges::elements_of, that's the whole name, no cap
π¦ Synopsis π¦
bestie it lives in <ranges>, obviously:
Defined in header <ranges>
template< ranges::range R, class Allocator =
std::allocator<std::byte> >
(since C++23)
struct elements_of;
so what does it actually do? it encapsulates a range. Specializations of elements_of act as a tag in overload sets to disambiguate when a range should be treated as a sequence rather than as a single value. that's the whole vibe check: "hey compiler, this range? i mean the stuff inside it, not the range itself as one thing." periodt β¨
π Template parameters π
Rβ a type that satisfiesrangeπAllocatorβ an allocator type that meets the requirements ofAllocatorπ
π Data members π
two of them, both public, both living their best life:
rangeβ a range of typeR(public member object) πallocatorβ an allocator of typeAllocator, and it has a default member initializer that value initializes itself (public member object) β
All these members are declared with the [[no_unique_address]] attribute. yes, both of them. the compiler is being thrifty and we respect it π
π§ Deduction guide π§
(since C++23) β here it is, character for character:
template< class R, class Allocator = std::allocator<std::byte> >
elements_of( R&&, Allocator = Allocator() ) -> elements_of<R&&,
Allocator>;
so you can just write std::ranges::elements_of(r) and the R&& gets deduced for you. slay π
π₯ Example π₯
// Run this code β go on, run it, i'll wait π«Ά
#include <any>
#include <generator>
#include <iostream>
#include <ranges>
#include <string_view>
template<bool Elementwise>
std::generator<std::any> gen(std::ranges::input_range auto&& r)
{
if constexpr (Elementwise)
co_yield std::ranges::elements_of(r); // yield each element of
r
else
co_yield r; // yield r as a single
value
}
int main()
{
auto test = std::string_view{"test"};
for (std::any a : gen<true>(test))
std::cout << '[' << std::any_cast<char>(a) << "] ";
std::cout << '\n';
for (std::any a : gen<false>(test))
std::cout << '[' << std::any_cast<std::string_view>(a) << "] ";
std::cout << '\n';
}
Output:
[t] [e] [s] [t]
[test]
see what happened there?? with gen<true> the elements_of tag made it yield each character one by one β [t] [e] [s] [t] β and with gen<false> it just yielded the whole string_view as one single value β [test]. that's literally the entire point of the tag, demonstrated in four lines. ate. π₯
π References π
- C++23 standard (ISO/IEC 14882:2023):
26.5.6 Class template elements_of [range.elementsof]
and that's the page!! π cute little struct, huge disambiguation energy. this was brought to you by http://cppreference.com, dated 2024.06.10, and the page itself is std::ranges::elements_of(3) β go forth and yield your ranges correctly bestie, ily πΈπ¦πβ¨
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms