Why std::optional is allowed to be compared to value?

2.9k Views Asked by At

It is very useful to be able to compare for equality a std::optional<T> with T:

std::optional<int> opt_value;
int value = 123;

opt_value == value; // will always be 'false'

I think the behavior in this case is well defined and clear.

What I do not get is why is this allowed:

opt_value < value; // this will always be 'true'

I was expecting this to not even compile. I think it is very obscure what is happening here. What is the reason why this has been even added to the STL?

3

There are 3 best solutions below

1
On

Short answer: map<optional<int>, int>
You want to be able to use optional<T> as a map key when T is usable as a key. Defining the empty state to be either less than or greater than the normal values makes it well behaved.

Meanwhile, comparing a plain T against an optional<T> should just, logically, upgrade the bare T to an optional<T> holding that value. So, providing an overloaded form that takes a bare T is just an optimization, and should have the same result.

1
On

In essence it allow you to more easily compare values. With this you don't have to write:

opt_value.value() < value;

It also checks to make sure opt_value has a value.

14
On

The proposal introducing optional to C++ states the conceptual idea of the type. An optional<T> is an object that augments the object type T with an additional value: nullopt. That's the idea of the type; it's a T that can have one extra value.

Given this reasoning, if T is ordered, then optional<T> should also be ordered. So the question now is not whether one should achieve this, but how to do so.

That answer will be arbitrary, but there are only two reasonable answers: either "not a T" is less than all values of T or it is greater than all values of T. They picked the former.