Date: Wed, 23 Sep 2020 18:12:51 -0400
On Wed, Sep 23, 2020 at 5:46 PM Eric Lengyel via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> > If it is only about discipline, why do you need this need to be in C++?
>
>
>
> It’s not about discipline at all. It’s about giving the compiler extra information that it can use to perform better optimizations. The addition of a qualifier to the type system does two things: (a) it allows proper overloading, and (b) it prevents the mistake of passing aliased storage to a function expecting disjoint storage, which is not prevented by restrict.
Is overloading something that's reasonable to do? I mean yes, `memcpy`
and `memmove` are distinct only because one requires disjoint ranges
and the other does not. But at the same time, I would rather see the
name of the function be different if they're going to take parameters
that are so significantly distinct from one another.
So what is the scenario in which it's really important for a function
to take both `disjoint` and non-disjoint objects?
Also, how is this supposed to work for higher-level types? Consider
`std::span`. Let's say we're taking an array of floats, and we require
that array to be `disjoint` from any other memory. So, do we take a
`span<disjoint float>`?
If so... how do we use it? `data` would presumably return a `disjoint
float*`, which is an out-right lie, since it is very much *not
disjoint*; you can modify the floats pointed to by that pointer by
using the `span` directly. Or by using another call to `data`. Does
`span::operator[]` return a `disjoint float&`? If so, how would that
work, considering that you can store that reference and get another
one that is very much not disjoint with the first?
And if a `span<disjoint T>` doesn't return `disjoint`
pointers/references... it's still lying because those pointers and
references still conflict with the `span<disjoint T>` itself, which
presumably is disjoint with .
In fact... is it even valid to copy a disjoint pointer? If you copy
it, then by definition there are two pointers pointing to the same
thing. So it cannot actually be `disjoint`. I mean, if it's going to
be part of the type system, then it should actually enforce
disjoint-ness to the degree possible, right?
`const` as part of the type system is good because the language makes
it *difficult* for you to violate it. One of the big problems with
`volatile` is that it doesn't prevent you from doing anything at all.
It's not a thing that lives at the programmer level; it lives at the
*compiler* level. It's about how the compiler interacts with the
object when it accesses it. So why is it part of the type system?
I don't think we need another one of those. If 90% of the onus is on
the programmer to keep the thing straight, and the main benefit is
about compiler behavior rather than programmer behavior, then I don't
see why it needs to be part of the type system.
<std-proposals_at_[hidden]> wrote:
>
> > If it is only about discipline, why do you need this need to be in C++?
>
>
>
> It’s not about discipline at all. It’s about giving the compiler extra information that it can use to perform better optimizations. The addition of a qualifier to the type system does two things: (a) it allows proper overloading, and (b) it prevents the mistake of passing aliased storage to a function expecting disjoint storage, which is not prevented by restrict.
Is overloading something that's reasonable to do? I mean yes, `memcpy`
and `memmove` are distinct only because one requires disjoint ranges
and the other does not. But at the same time, I would rather see the
name of the function be different if they're going to take parameters
that are so significantly distinct from one another.
So what is the scenario in which it's really important for a function
to take both `disjoint` and non-disjoint objects?
Also, how is this supposed to work for higher-level types? Consider
`std::span`. Let's say we're taking an array of floats, and we require
that array to be `disjoint` from any other memory. So, do we take a
`span<disjoint float>`?
If so... how do we use it? `data` would presumably return a `disjoint
float*`, which is an out-right lie, since it is very much *not
disjoint*; you can modify the floats pointed to by that pointer by
using the `span` directly. Or by using another call to `data`. Does
`span::operator[]` return a `disjoint float&`? If so, how would that
work, considering that you can store that reference and get another
one that is very much not disjoint with the first?
And if a `span<disjoint T>` doesn't return `disjoint`
pointers/references... it's still lying because those pointers and
references still conflict with the `span<disjoint T>` itself, which
presumably is disjoint with .
In fact... is it even valid to copy a disjoint pointer? If you copy
it, then by definition there are two pointers pointing to the same
thing. So it cannot actually be `disjoint`. I mean, if it's going to
be part of the type system, then it should actually enforce
disjoint-ness to the degree possible, right?
`const` as part of the type system is good because the language makes
it *difficult* for you to violate it. One of the big problems with
`volatile` is that it doesn't prevent you from doing anything at all.
It's not a thing that lives at the programmer level; it lives at the
*compiler* level. It's about how the compiler interacts with the
object when it accesses it. So why is it part of the type system?
I don't think we need another one of those. If 90% of the onus is on
the programmer to keep the thing straight, and the main benefit is
about compiler behavior rather than programmer behavior, then I don't
see why it needs to be part of the type system.
Received on 2020-09-23 17:13:01