C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Opt-In Compile Time Bounds Checking

From: Levo DeLellis <levo.delellis_at_[hidden]>
Date: Tue, 3 Oct 2023 19:49:30 -0500
There would be a breaking change if span was implemented as I
described nspan, and nspan wouldn't have a point if it didn't catch
the errors in test1 and test2.

In the code below if test1 and test2 used the described nspan then
there would be a compile error since 99 isn't in range and i isn't
checked to be in range. Changing span to work as nspawn would break
functions using span if they wrote it like test1 and test2. The point
of nspan is so test1 and test2 gets an error at compile time since
it's possible for the index to be out of bound.

#include <span>
#include <cstdio>

void test1(std::span<int, 4> myspan) {
    myspan[99] = 0;
}
void test2(std::span<int, 4> myspan, int i) {
    myspan[i] = 0;
}
void test3(std::span<int, 4> myspan, int len) {
    if (len >= 4) return;
    for(int i=0; i<len; i++) {
        myspan[i] = i*len;
    }
}

int main()
{
    int arr[] = {1, 5, 6, 8};
    test1(arr);
    test2(arr, 2);
    test2(arr, 99);
    test3(arr, 99);
}

On Tue, Oct 3, 2023 at 12:38 PM Arthur O'Dwyer
<arthur.j.odwyer_at_[hidden]> wrote:
>
> On Tue, Oct 3, 2023 at 2:21 AM Julien Jorge via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> Regarding the description of nspan, you wrote:
>>
>> > We don't use span because present day code uses it differently. For
>> example you can not pass span into a function with the same type but
>> smaller length.
>>
>> It seems to me that this restriction can be lifted by changing the
>> constraint of 24.7.2.2.2 §19.2 from
>>
>> extent == dynamic_extent
>> || OtherExtent == dynamic_extent
>> || extent == OtherExtent
>>
>> to
>>
>> extent == dynamic_extent
>> || OtherExtent == dynamic_extent
>> || extent <= OtherExtent
>>
>> And adjusting §20-22 accordingly.
>>
>> I don't know why the current wording is the way it is but I think you
>> should take this in consideration in your proposal, as adapting
>> std::span seems easier than introducing a whole new type :)
>
>
> I agree that messing with `span` would be easier than introducing `nspan`. However, I don't think even messing with `span` (in this respect) is a good idea.
> IMHO it's clear that `span<int>` (with dynamic_extent) is the most correct type to use when your spans are of varying width. If you're using `span<int, 24>` in your API, it's because you intend to accept only spans of exactly 24 ints — no more and no less. If someone accidentally tries to pass you a `span<int, 42>` (with an extra 18 entries at the end that your API is going to silently ignore), that's a bug that should be caught at compile time!
> If the caller knows what they're doing and really wants to pass "just the first 24 entries", they can write
> yourapi(mybigspan.subspan(0, 24));
> yourapi(std::span<int, 24>(mybigspan));
> or probably any number of variations — the important thing is that they have to write that subspan-truncating operation explicitly in their code.
> A span of 42 elements IS-NOT-A span of 24 elements; the domains of those two types are different; therefore the conversion between them should be explicit, not implicit.
>
> HTH,
> Arthur

Received on 2023-10-04 00:50:08