Самое минимальное требование необязательно <T> заключается в том, что T является полным типом и что он имеет общедоступный деструктор. T не обязательно должен быть конструируемым. Вы можете использовать минимальный интерфейс:
optional<T> o;
assert(o == none);
assert(!o);
o.value();
Но это практически бесполезно. Для того, чтобы необязательно<T> мог делать что-либо полезное и предлагать весь спектр способов доступа к содержащемуся значению, T должен иметь по крайней мере один доступный конструктор. В этом случае вам необходимо инициализировать необязательный объект с функцией emplace(), или если ваш компилятор не поддерживает его, прибегните к In-Place Factorys:
optional<T> o;
o.emplace("T", "ctor", "params");
Если T MoveConstructible, optional<T> также MoveConstructible и может быть легко инициализирован из r-значения типа T и передан по значению:
optional<T> o = make_T();
optional<T> p = optional<T>();
Если T CopyConstructible, optional<T> также CopyConstructible и может быть легко инициализирован из значения l типа T:
T v = make_T();
optional<T> o = v;
optional<T> p = o;
Если T не является MoveAssignable, все равно можно сбросить значение опционально<T> с помощью функции emplace():
optional<const T> o = make_T();
o.emplace(make_another_T());
Если T MoveConstructible и MoveAssignable, то optional<T> также Moveable и дополнительно может быть сконструирован и назначен из rзначения типа T.
Аналогично, если T является CopyableCopyConstructible и CopyAssignable, то optional<T> также Copyable и дополнительно может быть сконструирован и назначен из значения l типа T.
T не должно быть DefaultConstructible.