...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Type optional<T>
is
EqualityComparable
whenever T
is EqualityComparable
. Two optional
objects containing a value compare in the same way as their contained values.
The uninitialized state of optional<T>
is treated as a distinct value, equal to itself, and unequal to any value
of type T
:
boost::optional<int> oN = boost::none; boost::optional<int> o0 = 0; boost::optional<int> o1 = 1; assert(oN != o0); assert(o1 != oN); assert(o0 != o1); assert(oN == oN); assert(o0 == o0);
The converting constructor from T
as well as from boost::none
implies the existence and semantics
of the mixed comparison between T
and optional<T>
as
well as between none_t
and
optional<T>
:
assert(oN != 0); assert(o1 != boost::none); assert(o0 != 1); assert(oN == boost::none); assert(o0 == 0);
This mixed comparison has a practical interpretation, which is occasionally useful:
boost::optional<int> choice = ask_user(); if (choice == 2) start_procedure_2();
In the above example, the meaning of the comparison is 'user chose number 2'. If user chose nothing, he didn't choose number 2.
In case where optional<T>
is
compared to none
, it is not
required that T
be EqualityComparable
.
In a similar manner, type optional<T>
is LessThanComparable
whenever T
is LessThanComparable
. The optional
object containing no value is compared less than any value of T
. To illustrate this, if the default ordering
of size_t
is {0
, 1
,
2
, ...}, the default ordering
of optional<size_t>
is {boost::none
, 0
,
1
, 2
,
...}. This order does not have a practical interpretation. The goal is to
have any semantically correct default ordering in order for optional<T>
to
be usable in ordered associative containers (wherever T
is usable).
Mixed relational operators are the only case where the contained value of
an optional object can be inspected without the usage of value accessing
function (operator*
,
value
, value_or
).