Date: Sun, 3 Dec 2023 22:02:26 -0500
On Sun, Dec 3, 2023 at 9:51 PM Jason McKesson via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> On Sun, Dec 3, 2023 at 5:26 PM Thiago Macieira via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
> >
> > Some other code using NUA on your own types is wrong. One should only
> use NUA
> > for types that declare that they don't need unique addresses. There's no
> > property for this, therefore using NUA on arbitrary types is wrong.
>
> While I can understand that, I don't really agree.
>
> The primary purpose of NUA was for *empty* types, not to slip
> something into the padding bits of a non-empty type. Yes, that's a
> thing it *can* do, but that's not what it's for. Remember: the feature
> was added so that you could have the member equivalent of empty base
> optimizations. And one of the main purposes of EBO is for types like
> allocators which are frequently empty and thus should be declared NUA
> when they're members.
>
> So if "using NUA on arbitrary types is wrong", then the feature is
> fundamentally broken.
>
Using [[no_unique_address]] on *arbitrary* types *is* wrong.
Using [[no_unique_address]] on Allocator and Comparator members is
fine-and-expected; those types are (1) frequently empty and (2) always
understood by the client code to be value-semantic, i.e., the client code
will never try to take their address or "use" every byte of their storage.
What I think Thiago meant, and certainly what I mean, is that it's wrong to
use [[no_unique_address]] on the `value` member of an `optional` or
`expected`; it's wrong to use it on the pointer members of a `vector` or
`set`; it's wrong to use it on the `container` member of a
`priority_queue`; it's wrong to use it on the elements of a `tuple` or the
alternatives of a `variant`. It's wrong to use it *arbitrarily*.
The specific, limited, conservative, non-arbitrary place that it's okay to
use it is on a policy type like Allocator or Comparator or Predicate or
ExecutionPolicy that is expected to be empty most of the time. A client
programmer who provides a non-empty type for such a parameter is expected
to know what they're doing, and not to do anything too cavalier with
memcpy, address-escaping, or address-comparison.
–Arthur
std-proposals_at_[hidden]> wrote:
> On Sun, Dec 3, 2023 at 5:26 PM Thiago Macieira via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
> >
> > Some other code using NUA on your own types is wrong. One should only
> use NUA
> > for types that declare that they don't need unique addresses. There's no
> > property for this, therefore using NUA on arbitrary types is wrong.
>
> While I can understand that, I don't really agree.
>
> The primary purpose of NUA was for *empty* types, not to slip
> something into the padding bits of a non-empty type. Yes, that's a
> thing it *can* do, but that's not what it's for. Remember: the feature
> was added so that you could have the member equivalent of empty base
> optimizations. And one of the main purposes of EBO is for types like
> allocators which are frequently empty and thus should be declared NUA
> when they're members.
>
> So if "using NUA on arbitrary types is wrong", then the feature is
> fundamentally broken.
>
Using [[no_unique_address]] on *arbitrary* types *is* wrong.
Using [[no_unique_address]] on Allocator and Comparator members is
fine-and-expected; those types are (1) frequently empty and (2) always
understood by the client code to be value-semantic, i.e., the client code
will never try to take their address or "use" every byte of their storage.
What I think Thiago meant, and certainly what I mean, is that it's wrong to
use [[no_unique_address]] on the `value` member of an `optional` or
`expected`; it's wrong to use it on the pointer members of a `vector` or
`set`; it's wrong to use it on the `container` member of a
`priority_queue`; it's wrong to use it on the elements of a `tuple` or the
alternatives of a `variant`. It's wrong to use it *arbitrarily*.
The specific, limited, conservative, non-arbitrary place that it's okay to
use it is on a policy type like Allocator or Comparator or Predicate or
ExecutionPolicy that is expected to be empty most of the time. A client
programmer who provides a non-empty type for such a parameter is expected
to know what they're doing, and not to do anything too cavalier with
memcpy, address-escaping, or address-comparison.
–Arthur
Received on 2023-12-04 03:02:40