C++ Logo

std-proposals

Advanced search

Re: function at() for span<> that throws exception on out-of-range, like vector and array ::at()

From: Roman Babinicz <rb_at_[hidden]>
Date: Thu, 28 Nov 2019 14:46:55 +0100
On 28/11/2019 13:32, Ville Voutilainen wrote:
> On Thu, 28 Nov 2019 at 13:37, Roman Babinicz via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
>>
>>
>> Could we add operators at() to span<> container?
>>
>> value_type & at(size_type n);
>> const value_type & at(size_type n) const;
>>
>> they would have same behaviour as in vector, array - that is throws an
>> exception if n is outside of size of the container.
>>
>> 1) can we have that?
>>
>> 2) if yes, then should I write a proposal paper or how else to help in this?
>> Can it make it to C++20?
>>
>> Imo it is a notable defect that span can not be a drop in replacement
>> for code taking a (reference to) array/vector that is using at().
>>
>> 3)
>> By the way, in case of span that has specific size (not dynamic_extent)
>> we could perhaps have a static assert and the function might be constexpr.
>
> I predict this to be an uphill battle. Some audiences think that at()
> should have never been
> in vector, and adding it to array was a mistake, and that that mistake
> shouldn't propagate
> any further. I would guess that some such audiences are co-authors of span.
>
> Personally, I think they're wrong, but I'm just giving you a heads-up
> that this is not going to be
> a trivial sale.

Thanks for reply.

I have additional arguments why should we provide the ::at() .

This "battle" is generally happening here, on proposals mailing list, or
should some other place be contacted also?

Does writing the (trivial) paper proposal possibly help by being a
formal proposal, or should it be done only after full consensus in
discussion?


Without at() in span:

- developers have to rewrite the existing code to be able to upgrade
the (&vector) function into a more modern span<> which slows down
adoption of span

- developers who are used to at, will have to write own free-function
for it, or a small wrapper class around span - which is less readable:

at(data,i) = min(10, at(old_data, i+offset) )
data.at(i) = min(10, old_data.at(i+offset) )

score[ player_index[i] ] = ... ;
score.at( player_index.at(i) ) = ... ;
at(score, at(player_index,i) ) = ... ;

- also then does each project have to write such free function at, or
will this one be standardized? would make code more unreadable between
code bases

- in more complex expressions especially, the alternative to ::at() is I
suppose to manually assert the index and then use operator [i], but
consider expressions like

  draw( old_x.at(i), old_y.at(i+slowdown.at(frame)) + sky.at(i) ,
gfxtab.at(level) )

a separated out assert is more error prone, and much longer:

  if ( i >= old_x.size() ) throw std::overflow_error( "span bounds" );
  if ( i >= old_y.size() ) throw std::overflow_error( "span bounds" );
  if ( frame >= slowdown.size() ) throw std::overflow_error( "span
bounds" );
  if ( i >= sky.size() ) throw std::overflow_error( "span bounds" );
  if ( level >= gfxtab.size() ) throw std::overflow_error( "span
bounds" );
  draw( old_x[i], old_y[i+slowdown[frame]] + sky[i] , gfxtab[ level ]);

it also contains 1 or more like 2 bugs

- with at() it is nice and flexible and gives freedom to developer, if
he feels given code is not reviewed carefully enough then he might use
at(), or in security critical code; while in performance critical,
after review, he might want to place [i]


Personally I think it is good to by default write at() as the secure
code (at small cost), and only in places that are relevant to
performance change it to [] after careful review.

- array-bounds errors are one of most common sources of bugs and
exploits, and contribute to reputation of C++ being "error prone"
language among some users, it looks like a mistake to take away this
tool from developers who even care about this and started using at

Received on 2019-11-28 07:49:19