Why does std::span
only have begin
and end
methods and not their constant iterator counterparts cbegin
and cend
? (standard)
What I noticed too is that the proposals for span that I could find do have a definition for cbegin
and cend
: P0122R7. Why was it removed?
As an update, these are added back by P2278R4. The LWG issue pointed out below is still a problem, x.cbegin()
and std::cbegin(x)
would do different things, but now x.cbegin()
and std::ranges::cbegin(x)
do the same thing.
This was removed as a result of LWG3320.
The issue is that x.cbegin()
should really do the same thing as std::begin(std::as_const(x))
, which is what std::cbegin(x)
is defined as.
But that's not the case for std::span
, because it doesn't actually own its elements and, as a result, only has shallow const. Given span<int> s;
, s.cbegin()
would've given you an int const*
† while std::cbegin(s)
gives you an int*
. That's very inconsistent. Could've kept s.cbegin()
while having it just return begin()
(as proposed by PL 247), but that's arguably confusing, so the resolution decision was to simply remove all the const members and aliases.
In any case, std::cbegin(s)
always works if you want the container itself to be immutable (which isn't an issue with span
to begin with).
†Technically, implementation defined, not necessary int const*
, but this is a useful fiction for explanatory purposes.
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