Длинное название: почему std:variant
«s operator=(T&& t)
спецификация noexcept не зависит от спецификации noexcept деструктора внутренних типов?
Я могу видеть на cppreference тот
template <class T> variant& operator=(T&& t) noexcept(/* see below */);
является
noexcept(std::is_nothrow_assignable_v<T_j&, T> &&
std::is_nothrow_constructible_v<T_j, T>)
Итак, это компилируется:
struct FooThrow {
~FooThrow() noexcept(false) {throw;}
};
static_assert(std::is_nothrow_assignable_v<std::variant<FooThrow, int>, int>);
Но это вызывает FooThrow
деструктор который noexcept(false)
:
std::variant<FooThrow, int> x;
x = 3; // throws
Это не кажется правильным. Я что-то пропустил?
Как правило, стандартные типы библиотек не относятся к типам, имеющим деструкторы броска. Или, в частности, когда деструктор фактически выдает исключение. Там есть общее правило об этом ( [res.on.functions] )
В некоторых случаях (функции замены, функции-обработчики, операции над типами, используемыми для создания экземпляров стандартных шаблонных компонентов библиотеки) стандартная библиотека C ++ зависит от компонентов, предоставляемых программой C ++. Если эти компоненты не соответствуют их требованиям, этот международный стандарт не устанавливает требований к реализации.
В частности, эффекты не определены в следующих случаях:
…
- если какая-либо замещающая функция или функция-обработчик или операция деструктора завершается через исключение, если это специально не разрешено в соответствующем Обязательном поведении: параграф.
поскольку variant::operator=
не имеет специального утверждения о метании деструкторов, если эти деструкторы действительно выбрасывают — это UB.
Других решений пока нет …