On Thu, Jul 29, 2021 at 8:21 AM Григорий Шуренков via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Hi!

As far as I remember boost::optional<T&> has rather surprising assignment semantics when assigned from T& (rebind for empty optional and assign-through-reference for non-empty one).

It does not, there is no assign-through.
 
And it's the best it can achieve if it is modeled after optional<T>. That's why it was not standardized.

There is no reason why optional<T&> couldn't rebind on assignment. Multiple implementations of optional do this.
 
Maybe we just need another type - optional_reference<T>?  It can have different behavior more suitable for reference type.

Regards,
Gregory

The advantage of optional<T&> being spelled specifically optional<T&> is that it just works in generic code. optional<decltype(f())> is valid. This comes up a lot when you want to write operations that return a U or nothing and you don't know whether U is a reference type or not. An example here might be an algorithm that returns a reference (which may or may not be a true reference) to the first element of a range, if there is one. You just want to return optional<U>.

You don't want to return conditional_t<is_reference_v<U>, optional_reference<remove_reference_t<U>>, optional<U>>. I mean, doing that repeatedly would be a pain, so you'd just write something like... real_optional<U> that is either optional_reference<remove_reference_t<U>> or optional<U>. And then of course you'd want to ensure the same semantics in those cases, since the user of this algorithm might also be a different algorithm. And then why not just spell real_optional<U> as optional<U>?

Barry