- Можно ли вернуть
optional
из функцииconstexpr
? - Почему?
- Если да, как это работает?
Меня интересуют как boost::optional
, так и std::optional
. Они ведут себя одинаково?
optional
из функции constexpr
?Меня интересуют как boost::optional
, так и std::optional
. Они ведут себя одинаково?
boost::optional
не может быть возвращена функцией constexpr
. По крайней мере, документация не дает никаких гарантий.
Однако std::optional
, как определено принятым предложением С++ 14, может быть возвращено функцией constexpr
. Но только, если аргумент типа optional
тривиально разрушен.
Это позволяет деструктору std::optional
быть тривиальным в этих случаях. В этот момент нет никаких трудностей в уничтожении объекта, поэтому нет ничего, что останавливало бы std::optional
от буквального типа.
Это предложение совершенно очевидно. Если T
тривиально разрушается, то большинство конструкторов optional
будет constexpr
, а optional<T>
будет буквальным. И поэтому он может быть создан в функции constexpr
.
Boost.Optional не поддерживает constexpr
, главным образом потому, что он был написан до того, как был выпущен С++ 11.
Текущее предложение для std::optional
поддерживает constexpr
, если тип значения T
является тривиально разрушаемым. Он работает, потому что для союзов допустимы конструкторы constexpr
(7.1.5p4); компилятор отслеживает, какой член объединения инициализирован, гарантируя, что поведение undefined доступа к значению освобожденного необязательного значения происходит во время компиляции:
struct dummy_t {};
template <class T>
union optional_storage {
static_assert( is_trivially_destructible<T>::value, "" );
dummy_t dummy_;
T value_;
constexpr optional_storage(): dummy_{} {} // disengaged
constexpr optional_storage(T const& v): value_{v} {} // engaged
~optional_storage() = default;
};
Тип значения должен быть тривиально разрушаемым, потому что constexpr
полезен только для литералов, которые сами должны иметь тривиальный деструктор.
Например, запись:
constexpr optional_storage<int> o{};
constexpr int i = o.value_;
gcc дает ошибку:
error: accessing ‘optional_storage<int>::value_’ member instead of initialized
‘optional_storage<int>::dummy_’ member in constant expression