Wasn't the std::span
designed as a lightweight reference to sub-regions of std::vector
/std::array
/plain array and alike? Shouldn't it also contain comparison operators in its API, to be consistent with them? What was the reasoning behind the exclusion?
Note: by comparison operators, I mean either the full set (<
, <=
, ...) or the spaceship <=>
In addition to the requirement that std::array needs to be of compile-time constant length, the reason you would use it over std::vector is performance. std::array requires no dynamic memory allocation, and so can be much cheaper to use than std::vector in the case you know the number of elements.
A span provides a safe way to iterate over and index into objects that are arranged back-to-back in memory. Such as objects stored in a built-in array, std::array , or std::vector . If you typically access a sequence of back-to-back objects using a pointer and an index, a span is a safer, lightweight alternative.
Comparison operators are used to compare two values. Note: The return value of a comparison is either true ( 1 ) or false ( 0 ).
With C++20, the answer is quite easy: Use a std::span. A std::span stands for an object that can refer to a contiguous sequence of objects. A std::span, sometimes also called a view, is never an owner. This contiguous memory can be a plain array, a pointer with a size, a std::array, a std::vector, or a std::string.
As Daniel Langr pointed out, std::span
has comparison operators in its initial proposal P0122. These operators are then removed since the working draft N4791, and the reasons are stated in P1085.
In short, copy and const for std::span
are "shallow" (meaning copying a std::span
doesn't copy its underlying elements, and a const std::span
doesn't prevent its underlying elements from being modified), so comparisons, if exist, should also be "shallow" for consistency.
That paper gives the following examples:
Example 1:
T oldx = x;
change(x);
assert(oldx != x);
return oldx;
Example 2:
void read_only(const T & x);
void f()
{
T tmp = x;
read_only(x);
assert(tmp == x);
}
The assertions in these examples may fail if T = std::span
, while it doesn't for regular types.
One may argue that std::string_view
has shallow copy but deep comparisons. P1085 also has an explanation for this:
This matches
string_view
, howeverstring_view
can't modify the elements it points at, and thus the shallow copy ofstring_view
can be thought of as similar to a copy-on-write optimization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With