There is an ongoing debate about what optional
and variant
should do with reference types, particularly with regards to assignment. I would like to better understand the debate around this issue.
optional<T&> opt;
opt = i;
opt = j; // should this rebind or do i=j?
Currently, the decision is to make optional<T&>
ill-formed and make variant::operator=
ill-formed if any of the types is a reference type - to sidestep the argument and still give us most of the functionality.
What is the argument that opt = j
should rebind the underlying reference? In other words, why should we implement optional
like this:
template <class T>
struct optional<T&> {
T* ptr = nullptr;
optional& operator=(T& rhs) {
ptr = &rhs;
return *this;
}
};
What is the argument that opt = j should rebind the underlying reference?
I don't know what "the argument" you're looking for is. But you've just presented "an argument" for it:
optional<T&> opt;
opt = i;
opt = j;
Now, pretend that the second and third lines are far from each other. If you're just reading the code, what would you expect opt = j
to do? Or more to the point, why would you expect its behavior to differ from opt = i
?
To have the behavior of a wrapper type differ so drastically based purely on its current state would be very surprising.
Furthermore, we already have a way to communicate that you want to change the value inside the optional
. Namely: *opt = j
. This works just as well for optional<T&>
as it does for optional<T>
.
The way optional
works is very simple: it's a wrapper type. Like any currently existing wrapper types, operations on them affect the wrapper, not the thing being wrapped. To affect the thing being wrapped, you explicitly use *
or ->
or some other interface function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With