optional<T&>
was removed from the C++ standardization track because its use is questionable: it behaves nearly identically to a non-owning T*
with slightly different (and confusingly different from optional<T>
and T*
) semantics.
optional<T&>
is basically a non-owning T*
wrapped up pretty, and somewhat strangely.
Now, optional<T>
is a different beast.
I have used optional<Iterator>
in my container-based find algorithms. Instead of returning end()
, I return the empty optional. This lets users determine without a comparison if they have failed to find the item, and lets code like:
if(linear_search_for( vec, item))
work, while the same algorithm also lets you get at both the item and the location of the item in the container if you actually need it.
Pointers to elements doesn't give you the location information you might want except with contiguous containers.
So here, I've created a nullable iterator that has the advantages of iterators (generically working with different types of containers) and pointers (can be tested for the null state).
The next use is actually returning a value. Suppose you have a function that calculates a rectangle.
Rect GetRect();
now, this is great. But what if the question can be meaningless? Well, one approach is to return an empty rect or other "flag" value.
Optional lets you communicate that it can return a rect, or nothing, and not use the empty rect for the "nothing" state. It makes the return value nullable.
int GetValue();
is a better example. An invalid value could use a flag state of the int -- say -1
-- but that forces every user of your function to look up and track the flag state, and not accidentally treat it as a normal state.
Instead, optional<int> GetValue()
makes it clear that it can fail, and what the failure state it. If it is populated, you know it is a real value, and not a flag value.
In both of these cases, returning a non-owning pointer is non-viable, because who owns the storage? Returning an owning pointer is expensive, because pointless heap allocations are pointless.
Optionals are nullable value types. When you want to manage resources locally, and you still want an empty state, they make it clear.
Another thing to look into is the expected
type being proposed. This is an optional, but when in the empty state contains a reason why it is empty.
find
function returns a value type, e.g. anint
ordouble
? – Jehovistdouble
by value (or, better,int
by value), and you want to indicate you haven't found it, you'll return ... what? – Sanityoptional
at least makes things clearer for a user of an API. – EdettefindStudent()
create a new object? I'd guess not, but the API doesn't convey it. – Edetteoptional
solves this problem either by copying-by-value the result to the caller (or possibly moving it in C++11). Ownership now rests with the caller in the form of a temporary, which is then destroyed in a way that has clear semantics – Laureenoptional
is not so much a technical one, as just being clearer to developers that it's a type that may or may not have a value. Pointers have a lot of drawbacks. I won't list them here, butoptional
at least has RAII, which (raw) pointers lack. Perhaps you're presenting the perfect use-case for pointers, butoptional
has others, in some people's opinions. – Edette