...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
The very minimum requirement of optional<T>
is that T
is a complete type
and that it has a publicly accessible destructor. T
doesn't even need to be constructible. You can use a very minimum interface:
optional<T> o; // uninitialized assert(o == none); // check if initialized assert(!o); // o.value(); // always throws
But this is practically useless. In order for optional<T>
to be able to do anything useful and offer all the spectrum of ways of accessing
the contained value, T
needs
to have at least one accessible constructor. In that case you need to initialize
the optional object with function emplace()
, or if your compiler does not support it,
resort to In-Place
Factories:
optional<T> o; o.emplace("T", "ctor", "params");
If T
is MoveConstructible
,
optional<T>
is
also MoveConstructible
and
can be easily initialized from an rvalue of type T
and be passed by value:
optional<T> o = make_T(); optional<T> p = optional<T>();
If T
is CopyConstructible
, optional<T>
is
also CopyConstructible
and can be easily initialized from an lvalue of type T
:
T v = make_T(); optional<T> o = v; optional<T> p = o;
If T
is not MoveAssignable
, it is still possible to
reset the value of optional<T>
using function emplace()
:
optional<const T> o = make_T(); o.emplace(make_another_T());
If T
is Moveable
(both MoveConstructible
and
MoveAssignable
) then optional<T>
is
also Moveable
and additionally
can be constructed and assigned from an rvalue of type T
.
Similarly, if T
is Copyable
(both CopyConstructible
and CopyAssignable
) then optional<T>
is also Copyable
and additionally
can be constructed and assigned from an lvalue of type T
.
T
is not
required to be DefaultConstructible
.