Date: Tue, 14 Apr 2020 23:22:41 -0400
Dear Mario,
On Tue, Apr 14, 2020 at 9:52 PM Mario Charest via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> ...
> What is the rational for std::span not having an at() fonction, like most
> other contiguous container.
>
Because at() is a mistake for string view and all other cheap view types;
that we made the mistake with string_view is unfortunate.
There are two problems with at() as a member function, today.
The first is it's design. at() should not be a member function, and should
never have been implemented as one. at() should have been a free function
defined something like this:
template <typename Whatever>
decltype(auto) at (Whatever& __whatever, typename
::std::remove_cvref_t<Whatever>::difference_type __index)
noexcept(noexcept( ::std::data(__whatever))) {
if (std::size(__whatever) >= __index)
throw ::std::out_of_range("out of range");
return *(::std::data(__whatever) + __index);
}
This:
- Is not a member function so is decoupled from everything and does not
require exceptions baked into something that can live without it
- Makes it easy to pick between "I want checking" and "I don't want
checking", explicitly, by the user
- Works for every contiguous view/container, whether it exists in the
standard or not
It scales better, works nicer, and can be isolated with other such
"checking" functions. Very nice.
The second is the contention that comes from C++'s exceptions burden.
One of the biggest problems (and biggest benefits) of at() is that it
throws an exception on out-of-bounds. This is cute and nice and wonderful,
save for that in C++ this means bringing in a dependency on using "throw",
and throwing a standard exception. All standard exceptions defined in the
standard library -- out_of_range(), for example -- have a constructor that
takes a std::string, because the string view technology wasn't there yet.
This WOULD cost every person using the span header enormously, and makes
presenting these things in Freestanding-As-We-Would-Like-It -- with no
exceptions and other things -- difficult. std::string also transitively
does things like bring in iostreams and other header garbage. Many
implementations have spent plenty of man-hours trying to increase forward
declarations and other tricks to save on compile time for doing #include
<string>. If <span> had to do this, we would tank people's compile times
for just an exception and a string. Again.
Right now, <span> is a nice header that does not add an extra method for
bounds checking that drags in an exceptions dependency and a strings
dependency, and it would be well to keep this way for all eternity.
That being said, maybe an at() free function should be proposed and dumped
into some safety header for standard C++.
On Tue, Apr 14, 2020 at 9:52 PM Mario Charest via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> ...
> What is the rational for std::span not having an at() fonction, like most
> other contiguous container.
>
Because at() is a mistake for string view and all other cheap view types;
that we made the mistake with string_view is unfortunate.
There are two problems with at() as a member function, today.
The first is it's design. at() should not be a member function, and should
never have been implemented as one. at() should have been a free function
defined something like this:
template <typename Whatever>
decltype(auto) at (Whatever& __whatever, typename
::std::remove_cvref_t<Whatever>::difference_type __index)
noexcept(noexcept( ::std::data(__whatever))) {
if (std::size(__whatever) >= __index)
throw ::std::out_of_range("out of range");
return *(::std::data(__whatever) + __index);
}
This:
- Is not a member function so is decoupled from everything and does not
require exceptions baked into something that can live without it
- Makes it easy to pick between "I want checking" and "I don't want
checking", explicitly, by the user
- Works for every contiguous view/container, whether it exists in the
standard or not
It scales better, works nicer, and can be isolated with other such
"checking" functions. Very nice.
The second is the contention that comes from C++'s exceptions burden.
One of the biggest problems (and biggest benefits) of at() is that it
throws an exception on out-of-bounds. This is cute and nice and wonderful,
save for that in C++ this means bringing in a dependency on using "throw",
and throwing a standard exception. All standard exceptions defined in the
standard library -- out_of_range(), for example -- have a constructor that
takes a std::string, because the string view technology wasn't there yet.
This WOULD cost every person using the span header enormously, and makes
presenting these things in Freestanding-As-We-Would-Like-It -- with no
exceptions and other things -- difficult. std::string also transitively
does things like bring in iostreams and other header garbage. Many
implementations have spent plenty of man-hours trying to increase forward
declarations and other tricks to save on compile time for doing #include
<string>. If <span> had to do this, we would tank people's compile times
for just an exception and a string. Again.
Right now, <span> is a nice header that does not add an extra method for
bounds checking that drags in an exceptions dependency and a strings
dependency, and it would be well to keep this way for all eternity.
That being said, maybe an at() free function should be proposed and dumped
into some safety header for standard C++.
Received on 2020-04-14 22:25:50