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 this:
template
struct span
{
T * ptr_to_array; // pointer to a contiguous C-style array of data
// (which memory is NOT allocated or deallocated
// by the span)
std::size_t length; // number of elements in the array
// Plus a bunch of constructors and convenience accessor methods here
}
It is a light-weight wrapper around a C-style array, preferred by C++ developers whenever they are using C libraries and want to wrap them with a C++-style data container for "type safety" and "C++-ishness" and "feelgoodery". :)
@einpoklum does a pretty good job of introducing what a span is in his answer here. However, even after reading his answer, it is easy for someone new to spans to still have a sequence of stream-of-thought questions which aren't fully answered, such as the following:
span different from a C array? Why not just use one of those? It seems like it's just one of those with the size known as well...std::array, how is a span different from that?std::vector like a std::array too?span?So, here's some additional clarity on that:
DIRECT QUOTE OF HIS ANSWER--WITH MY ADDITIONS and parenthetical comments IN BOLD and my emphasis in italics:
What is it?
A
spanis:
- A very lightweight abstraction of a contiguous sequence of values of type
Tsomewhere in memory.- Basically a single struct
{ T * ptr; std::size_t length; }with a bunch of convenience methods. (Notice this is distinctly different fromstd::array<>because aspanenables convenience accessor methods, comparable tostd::array, via a pointer to typeTand length (number of elements) of typeT, whereasstd::arrayis an actual container which holds one or more values of typeT.)- A non-owning type (i.e. a "reference-type" rather than a "value type"): It never allocates nor deallocates anything and does not keep smart pointers alive.
It was formerly known as an array_view and even earlier as array_ref.
Those bold parts are critical to one's understanding, so don't miss them or misread them! A span is NOT a C-array of structs, nor is it a struct of a C-array of type T plus the length of the array (this would be essentially what the std::array container is), NOR is it a C-array of structs of pointers to type T plus the length, but rather it is a single struct containing one single pointer to type T, and the length, which is the number of elements (of type T) in the contiguous memory block that the pointer to type T points to! In this way, the only overhead you've added by using a span are the variables to store the pointer and length, and any convenience accessor functions you use which the span provides.
This is UNLIKE a std::array<> because the std::array<> actually allocates memory for the entire contiguous block, and it is UNLIKE std::vector<> because a std::vector is basically just a std::array that also does dynamic growing (usually doubling in size) each time it fills up and you try to add something else to it. A std::array is fixed in size, and a span doesn't even manage the memory of the block it points to, it just points to the block of memory, knows how long the block of memory is, knows what data type is in a C-array in the memory, and provides convenience accessor functions to work with the elements in that contiguous memory.
std::span is part of the C++ standard as of C++20. You can read its documentation here: https://en.cppreference.com/w/cpp/container/span. To see how to use Google's absl::Span in C++11 or later today, see below.
std::span (Extent = "the number of elements in the sequence, or std::dynamic_extent if dynamic". A span just points to memory and makes it easy to access, but does NOT manage it!):std::array (notice it has a fixed size N!):std::vector (automatically dynamically grows in size as necessary):span in C++11 or later today?Google has open-sourced their internal C++11 libraries in the form of their "Abseil" library. This library is intended to provide C++14 to C++20 and beyond features which work in C++11 and later, so that you can use tomorrow's features, today. They say:
Compatibility with the C++ Standard
Google has developed many abstractions that either match or closely match features incorporated into C++14, C++17, and beyond. Using the Abseil versions of these abstractions allows you to access these features now, even if your code is not yet ready for life in a post C++11 world.
span.h header, and absl::Span(array, length) template class: https://github.com/abseil/abseil-cpp/blob/master/absl/types/span.h#L153