Copy assignment revisited
Remember the ints
With int
s we can do something like this.
If we are trying to do something similar with our optional in a new test case, we will get an compiler error.
The compiler error will basically look like this:
It is complaining, that there is no conversion from void
to `const optional
Copy assignment operator’s signature revisited
Let’s revisited the signature of our optional’s copy assignment operator.
We already saw, that the assignment operator has a member function like
call syntax, meaning that we can transform
a = b
to a.operator=(b)
. This implies, that we can our example from above rewrite to:
We are assigning the return value of y.operator=(x)
to z
, but the return value of optional’s assignment operator
is void
. This explains the compilers error message: y.operator=(x)
returns void
, which can not be converted to
const optional<int>&
– it wouldn’t make any sense anyways.
So, in order to allow this usage of the assignment operator, we need to change it’s return value. We need to somehow
return the new value of y
. We could do it be returning a copy of y
by value, but this is quite wasteful, this copy
would be temporary and directly destroyed after the second assignment. It makes way more sense to return a reference to
y
.
With this implementation, our new test compiles and succeeds. Note, that we are returning a non-const reference here.
One could argue, that it makes more sense to return a constant reference here.
F.47 of the
C++ Core Guideliens discourages this due to consistency with standard types: e.g. int
s assignment operator behaves
like it would return a non-const reference. (a = b) = c
is possible with int
s but would not be possible, if the
assignment operator would return a constant reference.
Conclusion
optional should now behave like a int
copy assignment wise. Actually, it should new behave in the very most cases
like an int
consistently.
From my point of view, our optional as it is now, can be considered to be “the minimal core” of an optional to be usfull, having the following characteristics:
- It encapsulates a
union
and abool
making it a tagged union. - It is a regular type.
This is the core functionally of an optional. (Almost) everything else is about syntactic sugar and optimizations. But I am positive, that implementing these will be educational and fun anyways.