C++ Basics: Pass Contiguous Data with std::span
A pointer alone does not describe a sequence length. std::span packages a pointer and an extent for contiguous data while leaving ownership with the caller.
Prepare a scratch directory
Tested on Linux x86_64 with GCC 14.2.0. Install G++ and its C++ standard-library development files, and make g++ available on PATH. You also need Bash, a text editor, and mktemp, rm, and rmdir. No third-party C++ library is required.
Keep the same terminal open. Stop if setup fails, before saving the source:
start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1Run the example
Save this as span-nonowning-bounds-demo.cpp:
#include <array>
#include <iostream>
#include <span>
void print_values(std::span<const int> values)
{
std::cout << "Count: " << values.size() << "; values:";
for (const int value : values) {
std::cout << ' ' << value;
}
std::cout << '\n';
}
int main()
{
std::array<int, 4> samples{10, 20, 30, 40};
const std::span<const int> all_samples{samples};
print_values(all_samples);
const std::size_t offset = 1;
const std::size_t count = 2;
if (offset > all_samples.size() ||
count > all_samples.size() - offset) {
return 1;
}
const auto middle_samples = all_samples.subspan(offset, count);
print_values(middle_samples);
samples[1] = 25;
print_values(middle_samples);
}Compile and run it. The second command runs only after compilation succeeds:
g++ -std=c++20 -Wall -Wextra -Werror -pedantic span-nonowning-bounds-demo.cpp -o span-nonowning-bounds-demo &&
./span-nonowning-bounds-demoObserved output:
Count: 4; values: 10 20 30 40
Count: 2; values: 20 30
Count: 2; values: 25 30Read the result
The full span contains four elements. Its checked subview refers to the middle two. Updating the underlying array changes the value observed through that subview. The const element type prevents mutation through these spans; it does not make the owning array immutable.
Apply it carefully
In C++20, span indexing and subspan do not provide general runtime bounds checking. Validate dynamic offsets and counts before creating a subview. The subtraction is performed only after the offset is known to be within the span, avoiding unsigned underflow. The owner must remain alive and its storage must remain valid for every use of the span. This example uses std::array, whose storage does not reallocate.
The C++ working draft specifies the relevant library behavior. The example uses interfaces available in C++20; the current working draft also describes later additions.
Clean up
Remove only the source and executable created here, then return to the starting directory:
rm -- span-nonowning-bounds-demo.cpp span-nonowning-bounds-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directoryIf the directory is not empty, inspect the remaining contents before removing anything else.
Acknowledgements
This post was created with assistance from AI.