optional
из constexpr
функционировать? Я заинтересован в обоих boost::optional
а также std::optional
, Они ведут себя одинаково?
boost::optional
не может быть возвращен constexpr
функция. Или, по крайней мере, документация не дает гарантии этого.
Тем не мение, std::optional
в соответствии с принятым предложением C ++ 14, Можно быть возвращенным constexpr
функция. Но только если аргумент типа optional
тривиально разрушаемо.
Это позволяет деструктору std::optional
быть тривиальным в этих случаях. В этот момент нетрудно уничтожить объект, поэтому ничто не мешает std::optional
из буквального типа.
Предложение вполне понятно по этому вопросу. Если T
тривиально разрушаемо, то большинство конструкторов optional
будет constexpr
, а также optional<T>
будет буквальным типом. И, следовательно, он может быть создан в constexpr
функция.
Boost.Optional не поддерживает constexpr
Главным образом потому, что он был написан до выпуска C ++ 11.
текущее предложение для std::optional
поддерживает constexpr
, пока тип значения T
тривиально разрушаемо. Это работает потому что constexpr
конструкторы разрешены для союзов (7.1.5p4); компилятор отслеживает, какой элемент объединения инициализирован, гарантируя, что неопределенное поведение доступа к значению отключенного необязательного параметра будет обнаружено во время компиляции:
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