Date: Tue, 3 Oct 2023 08:21:44 +0200
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 :)
Julien
On 01/10/2023 00:18, Levo DeLellis wrote:
> Sorry for the delay, I rarely check my email
>
> In your first example you are correct that my proposal would not
> understand `i` is always in bounds. I don't think I ever had a
> situation where I checked the bounds of an array in a different loop
> and I don't remember anytime I did it in another function although I
> probably have at some point
> This is one reason why I wanted a unique type which is used
> optionally. Since that situation is not caught it'd perhaps be better
> for the programmer to choose to A) Convert it to another type such as
> span which won't require checks B) Move the check into the second loop
> if possible (ie there's no side effects so there's no need to return
> early) C) Rewrite code because you want to check to succeed. In the
> compiler I written most of the time I never run into the problem with
> the check being too trivial. Sieve of Eratosthenes is another place
> where the check fails but most of the time the check works and there
> are no hoops to jump through
>
> With your second question, I'm suggesting the call site should cause
> the ambiguous error as you written. The implementation of the two
> functions could possibly be the same except maybe the larger one has
> SIMD optimizations. But there's also a good chance a user copy/pasted
> code twice, changed the size of one of the array and have no idea they
> are calling two different functions. However I'm not opposed to
> allowing the larger one being the function called, I just think it's
> likely to be error prone. If this is allowed there should be a warning
> so people can make it an error
>
>
> On Wed, Sep 27, 2023 at 2:23 AM Julien Jorge <julien.jorge_at_[hidden]> wrote:
>> On 10/09/2023 07:14, Levo DeLellis via Std-Proposals wrote:
>>> Attached is a proposal for safespan and nspan which requires certain
>>> things to be known at compile time.
>>>
>> Hello, I gave a quick look at your proposal and I have a couple of
>> questions :)
>>
>> Regarding safespan, if I understood correctly there cannot be an access
>> without prior test confirming that the index is within the bounds. I
>> wonder how it can be assured for non-trivial indices. Especially, it
>> seems to prevent any sort of pre-validation of the indices like in the
>> code below:
>>
>> void foo(std::safespan<int> values, std::safespan<std::size_t> order)
>> {
>> bool valid = true;
>>
>> for (std::size_t i : order)
>> if (i >= values.size())
>> return;
>>
>> // All indices are known to be within the bounds here.
>> for (std::size_t i : order)
>> bar(values[i])
>> }
>>
>> It may be obvious for the programmer that the indices are valid in the
>> second loop (at least ignoring potential side effects of `bar` on
>> `order`) but it is non-trivial for the compiler. This specification in
>> point 2.B in your proposal makes me wondering if this type would
>> actually be useful for not very specific, maybe trivial, code. Do you
>> have more complex examples to share? My goal here is to understand the
>> scope of the feature and see the alternatives when we cannot meet this
>> scope.
>>
>> Regarding nspan you wrote:
>>
>> > Because it is useful to have implicit conversions it should be
>> ambiguous to use function overloading when the nspan parameter is the
>> only difference.
>>
>> I am not sure if you are suggesting a standard-backed special case for
>> handling function overload declarations or if you are talking about
>> ambiguity on the call site. With regard to your specification, namely
>> the point "May be implicitly converted to a nspan of same or smaller
>> size but never larger", I think the latter works out of the box:
>>
>> void foo(std::nspan<int, 24>);
>> void foo(std::nspan<int, 42>);
>>
>> std::nspan<int, 128> s = …;
>> foo(s); // Ambiguous: s is implicitly convertible to
>> // both std::nspan<int, 24> and std::nspan<int, 42>
>>
>> Best regards,
>> Julien
>>
> 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 :)
Julien
On 01/10/2023 00:18, Levo DeLellis wrote:
> Sorry for the delay, I rarely check my email
>
> In your first example you are correct that my proposal would not
> understand `i` is always in bounds. I don't think I ever had a
> situation where I checked the bounds of an array in a different loop
> and I don't remember anytime I did it in another function although I
> probably have at some point
> This is one reason why I wanted a unique type which is used
> optionally. Since that situation is not caught it'd perhaps be better
> for the programmer to choose to A) Convert it to another type such as
> span which won't require checks B) Move the check into the second loop
> if possible (ie there's no side effects so there's no need to return
> early) C) Rewrite code because you want to check to succeed. In the
> compiler I written most of the time I never run into the problem with
> the check being too trivial. Sieve of Eratosthenes is another place
> where the check fails but most of the time the check works and there
> are no hoops to jump through
>
> With your second question, I'm suggesting the call site should cause
> the ambiguous error as you written. The implementation of the two
> functions could possibly be the same except maybe the larger one has
> SIMD optimizations. But there's also a good chance a user copy/pasted
> code twice, changed the size of one of the array and have no idea they
> are calling two different functions. However I'm not opposed to
> allowing the larger one being the function called, I just think it's
> likely to be error prone. If this is allowed there should be a warning
> so people can make it an error
>
>
> On Wed, Sep 27, 2023 at 2:23 AM Julien Jorge <julien.jorge_at_[hidden]> wrote:
>> On 10/09/2023 07:14, Levo DeLellis via Std-Proposals wrote:
>>> Attached is a proposal for safespan and nspan which requires certain
>>> things to be known at compile time.
>>>
>> Hello, I gave a quick look at your proposal and I have a couple of
>> questions :)
>>
>> Regarding safespan, if I understood correctly there cannot be an access
>> without prior test confirming that the index is within the bounds. I
>> wonder how it can be assured for non-trivial indices. Especially, it
>> seems to prevent any sort of pre-validation of the indices like in the
>> code below:
>>
>> void foo(std::safespan<int> values, std::safespan<std::size_t> order)
>> {
>> bool valid = true;
>>
>> for (std::size_t i : order)
>> if (i >= values.size())
>> return;
>>
>> // All indices are known to be within the bounds here.
>> for (std::size_t i : order)
>> bar(values[i])
>> }
>>
>> It may be obvious for the programmer that the indices are valid in the
>> second loop (at least ignoring potential side effects of `bar` on
>> `order`) but it is non-trivial for the compiler. This specification in
>> point 2.B in your proposal makes me wondering if this type would
>> actually be useful for not very specific, maybe trivial, code. Do you
>> have more complex examples to share? My goal here is to understand the
>> scope of the feature and see the alternatives when we cannot meet this
>> scope.
>>
>> Regarding nspan you wrote:
>>
>> > Because it is useful to have implicit conversions it should be
>> ambiguous to use function overloading when the nspan parameter is the
>> only difference.
>>
>> I am not sure if you are suggesting a standard-backed special case for
>> handling function overload declarations or if you are talking about
>> ambiguity on the call site. With regard to your specification, namely
>> the point "May be implicitly converted to a nspan of same or smaller
>> size but never larger", I think the latter works out of the box:
>>
>> void foo(std::nspan<int, 24>);
>> void foo(std::nspan<int, 42>);
>>
>> std::nspan<int, 128> s = …;
>> foo(s); // Ambiguous: s is implicitly convertible to
>> // both std::nspan<int, 24> and std::nspan<int, 42>
>>
>> Best regards,
>> Julien
>>
Received on 2023-10-03 06:21:48