Recently I\'ve gotten suggestions to use span
\'s in my code, or have seen some answers here on the site which use span
\'s - supposedly som
A span
is:
T
somewhere in memory.struct { T * ptr; std::size_t length; }
with a bunch of convenience methods.It was formerly known as an array_view and even earlier as array_ref.
First, when not to use it:
std::sort
, std::find_if
, std::copy
and all of those super-generic templated functions.Now for when to actually use it:
Use
span
(respectively,span
) instead of a free-standingT*
(respectivelyconst T*
) for which you have the length value. So, replace functions like:void read_into(int* buffer, size_t buffer_size);
with:
void read_into(span
buffer);
Oh, spans are awesome! Using a span
...
means that you can work with that pointer+length / start+end pointer combination like you would with a fancy, pimped-out standard library container, e.g.:
for (auto& x : my_span) { /* do stuff */ }
std::find_if(my_span.cbegin(), my_span.cend(), some_predicate);
... but with absolutely none of the overhead most container classes incur.
lets the compiler do more work for you sometimes. For example, this:
int buffer[BUFFER_SIZE];
read_into(buffer, BUFFER_SIZE);
becomes this:
int buffer[BUFFER_SIZE];
read_into(buffer);
... which will do what you would want it to do. See also Guideline P.5.
is the reasonable alternative to passing const vector
to functions when you expect your data to be contiguous in memory. No more getting scolded by high-and-mighty C++ gurus!
facilitates static analysis, so the compiler might be able to help you catch silly bugs.
allows for debug-compilation instrumentation for runtime bounds-checking (i.e. span
's methods will have some bounds-checking code within #ifndef NDEBUG
... #endif
)
indicates that your code (that's using the span) doesn't own the pointed-to memory.
There's even more motivation for using span
s, which you could find in the C++ core guidelines - but you catch the drift.
std::span has actually been added to the standard library - but only as of C++20. While the idea is not new - its current form was conceived in conjunction with the C++ core guidelines project, which only started taking shape in 2015.
It's part of the Core Guidelines's Support Library (GSL). Implementations:
span
.The GSL implementation does generally assume a platform that implements C++14 support [11]. These alternative single-header implementations do not depend on GSL facilities:
Note that these different span implementations have some differences in what methods/support functions they come with; and they may also differ somewhat from the version going into the standard libraryin C++20.
Further reading: You can find all the details and design considerations in the final official proposal before C++17, P0122R7: span: bounds-safe views for sequences of objects by Neal Macintosh and Stephan J. Lavavej. It's a bit long though. Also, in C++20, the span comparison semantics changed (following this short paper by Tony van Eerd).