Recently I've gotten suggestions to use span<T>'s in my code, or have seen some answers here on the site which use span's - supposedly some kind of container. But - I can't find anything like that in the C++17 standard library.
So what is this mysterious span<T>, and why (or when) is it a good idea to use it?
What is it?
A
span<T>is:Tsomewhere in memory.struct { T * ptr; std::size_t length; }with a bunch of convenience methods.It was formerly known as an
array_viewand even earlier asarray_ref.When should I use it?
First, when not to use spans:
std::sort,std::find_if,std::copyand other templated functions from<algorithm>), and also not in code that takes an arbitrary range (see The C++20 ranges library for information about those). A span has stricter requirements than a pair of iterators or a range: element contiguity and presence of the elements in memory.Now for when to actually use a span:
Why should I use it? Why is it a good thing?
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);std::ranges::find_if(my_span, some_predicate);(in C++20)... but with absolutely none of the overhead most container classes incur.
lets the compiler do more work for you sometimes. For example, this:
becomes this:
... which will do what you would want it to do. See also Guideline P.5.
is the reasonable alternative to passing
const vector<T>&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
spans, which you could find in the C++ core guidelines - but you catch the drift.But is it in the standard library?
edit: Yes,
std::spanwas added to C++ with the C++20 version of the language!Why only in C++20? Well, 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. So it took a while.
So how do I use it if I'm writing C++17 or earlier?
It's part of the Core Guidelines's Support Library (GSL). Implementations:
gsl/spanspan<T>.The GSL implementation does generally assume a platform that implements C++14 support [12]. These alternative single-header implementations do not depend on GSL facilities:
martinmoene/span-literequires C++98 or latertcbrindle/spanrequires C++11 or laterNote 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 adopted into the standard library in 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).