Date: Mon, 2 Aug 2021 09:35:15 -0500
On Mon, Aug 2, 2021 at 9:29 AM Ville Voutilainen via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> On Mon, 2 Aug 2021 at 17:18, Jason McKesson via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> >
> > On Mon, Aug 2, 2021 at 6:26 AM Andrey Semashev via Std-Proposals
> > <std-proposals_at_[hidden]> wrote:
> > >
> > > On 8/2/21 12:28 PM, Lénárd Szolnoki via Std-Proposals wrote:
> > > >
> > > > The Achilles' heel of optional<T&> seems to be assignment. I'm of the
> > > > opinion that it simply shouldn't have assignment from arguments of
> type
> > > > T, but I believe there is no perfect answer.
> > >
> > > Personally, I have no problem with rebinding semantics of
> > > optional<T&>::operator=(T&). That it would affect the referred object
> > > makes no sense because (a) there may not be such an object (if the
> > > optional is empty) and (b) no other version of optional<T> acts this
> > > way.
> >
> > Um, yes they do. If you have an engaged `optional<T>`, and you assign
> > a `T` to it, it assigns to the engaged value. It does not
> > unengage/re-engage itself.
> >
> > So if you have this:
> >
> > ```
> > optional<T> t = ...; //some T
> > T& t_ref = *t;
> > t = ...; //some other T
> > ```
> >
> > If each of those pieces of code is valid, then `t_ref` is also valid.
> > It still refers to the value you assigned to the `t`.
> >
> > The semantics you want for `optional<T&>` violate this. The `t_ref` in
> > this case would refer to the old referenced object, not the new one.
>
> That, to me, seems like an almost "of course" level reason for having
> the assignment "assign through" if
> an optional<T&> is engaged. If it's engaged, it invokes the assignment
> of the held entity, and if that has reference
> semantics, so be it.
>
Except it's the wrong semantic, which is why precisely zero implementations
of optional that support references (and there are several) do this. And
it's the wrong semantic because it has wildly different behavior based on
initial state, and thus basically has no meaningful semantic behavior that
you can rely on. Something something standardizing a wealth of existing
practice.
The right semantic is the assignment does actually do "unengage/re-engage"
and the right way to think about it is that optional *already does this*.
Except that since for many types, assignment can be much more efficient
then destroy/construct, we defer to the assignment operator. It's just that
for references, we know that this is wrong, so we can avoid doing it.
Barry
std-proposals_at_[hidden]> wrote:
> On Mon, 2 Aug 2021 at 17:18, Jason McKesson via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> >
> > On Mon, Aug 2, 2021 at 6:26 AM Andrey Semashev via Std-Proposals
> > <std-proposals_at_[hidden]> wrote:
> > >
> > > On 8/2/21 12:28 PM, Lénárd Szolnoki via Std-Proposals wrote:
> > > >
> > > > The Achilles' heel of optional<T&> seems to be assignment. I'm of the
> > > > opinion that it simply shouldn't have assignment from arguments of
> type
> > > > T, but I believe there is no perfect answer.
> > >
> > > Personally, I have no problem with rebinding semantics of
> > > optional<T&>::operator=(T&). That it would affect the referred object
> > > makes no sense because (a) there may not be such an object (if the
> > > optional is empty) and (b) no other version of optional<T> acts this
> > > way.
> >
> > Um, yes they do. If you have an engaged `optional<T>`, and you assign
> > a `T` to it, it assigns to the engaged value. It does not
> > unengage/re-engage itself.
> >
> > So if you have this:
> >
> > ```
> > optional<T> t = ...; //some T
> > T& t_ref = *t;
> > t = ...; //some other T
> > ```
> >
> > If each of those pieces of code is valid, then `t_ref` is also valid.
> > It still refers to the value you assigned to the `t`.
> >
> > The semantics you want for `optional<T&>` violate this. The `t_ref` in
> > this case would refer to the old referenced object, not the new one.
>
> That, to me, seems like an almost "of course" level reason for having
> the assignment "assign through" if
> an optional<T&> is engaged. If it's engaged, it invokes the assignment
> of the held entity, and if that has reference
> semantics, so be it.
>
Except it's the wrong semantic, which is why precisely zero implementations
of optional that support references (and there are several) do this. And
it's the wrong semantic because it has wildly different behavior based on
initial state, and thus basically has no meaningful semantic behavior that
you can rely on. Something something standardizing a wealth of existing
practice.
The right semantic is the assignment does actually do "unengage/re-engage"
and the right way to think about it is that optional *already does this*.
Except that since for many types, assignment can be much more efficient
then destroy/construct, we defer to the assignment operator. It's just that
for references, we know that this is wrong, so we can avoid doing it.
Barry
Received on 2021-08-02 09:35:31