Given a function that accepts a range, for example:
void f(const std::ranges::range auto& r);
Sometimes I have only one element that I want to pass to the function.
There are multiple ways of creating a single-element range for this purpose, for example:
int i{};
/*1*/ f(std::array{i});
/*2*/ f(std::span{&i, 1});
/*3*/ f(std::ranges::views::single(i));
All of those work, but I'd like to know if there are practical differences (efficiency?) between them and if any of them (or a different one) should be preferred.
(The question is tagged with both C++20
and C++23
in case there are differences between the versions that affect the answer)
If you need to store a range adaptor constructed from r
, e.g. std::views::concat(r, something)
:
r
is an lvalue of std::array{i}
: Because std::array
does not model view
, the resulting range adaptor will store a pointer to r
.r
is std::span{&i, 1}
: The resulting range adaptor will store a copy of r
, which contains a pointer to i
.r
is std::views::single(i)
: The resulting range adaptor will store a copy of r
, which contains a copy of i
.If r
is an rvalue of std::array{i}
, the range adaptor will also store a copy (effectively equivalent to std::views::single(i)
, but with an extra wrapper).
In general, I'd recommend to use std::view::single(i)
because it's least likely to produce dangling pointers, unless the object i
is very expensive to copy.