On Tue, Apr 14, 2020 at 11:23 PM JeanHeyd Meneide via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Tue, Apr 14, 2020 at 9:52 PM Mario Charest via Std-Proposals <std-proposals@lists.isocpp.org> 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 its design — nit: I don't think this is a "problem"; I think this is "your preferred solution to the second problem." Me personally, I definitely want it to be a member function, for ergonomics; and I would want it to work on any random-access range, even `deque`. I would also want some exploration of the existing std::map facility: should m.at(idx) mean (idx < m.size() ? m[idx] : throw out_of_range()), and if not, why not? Generic programming requires extracting the commonalities between different possible parameter types, and I don't think that work is entirely done yet.)

     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

Yes. This is the (IMO only) reason that std::span lacks `at()`.
However, it is the odd one out. Even std::string_view has an `at()` method. So I think it's a mistake to omit it for `span`.

I would like to see some work in the direction of "features arising out of the conglomeration of two features." What I mean is that maybe if you just `#include <span>` you don't get an .at() function, but if you do
    #include <span>
    #include <stdexcept>
(in either order) then you get an .at() function. (And in some way that doesn't violate the ODR. That'd be the tricky part.)
Of course you can already do kind-of-this today: if you do
    #include <span>
    #include <my/at.h>
then you get a my::at(const T&) free function template. But again, free functions are bad for ergonomics.

However, I'd like to see that work being done on analogous problems in real codebases and then contributed back upstream as "industry experience," not designed-by-committee directly into the paper standard. ;)

Re freestanding and compile times: I wonder whether embedded vendors are going to implement modules; and, if they do, wouldn't they just put in a no-exceptions mode where the standard library doesn't provide .at() in that mode? Does modules make this any easier (or harder) than the state of the art?

my $.02,
–Arthur