Почему спецификация noexcept `operator = (T && t)` `std: variable` не зависит от спецификации noexcept деструктора внутренних типов? - PullRequest
0 голосов
/ 08 октября 2018

Длинное название: Почему спецификация std:variant s operator=(T&& t) не зависит от спецификации noexcept деструктора внутренних типов?

Я вижу по cppreference , что

template <class T> variant& operator=(T&& t) noexcept(/* see below */);

is

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

Это не кажется правильным.Я что-то упустил?

1 Ответ

0 голосов
/ 08 октября 2018

Как правило, стандартные типы библиотек не относятся к типам, имеющим деструкторы броска.Или, в частности, когда деструктор фактически выдает исключение.Об этом есть общее правило ( [res.on.functions] )

В некоторых случаях (функции замены, функции-обработчики, операции над типами, используемые для создания экземпляров стандартных шаблонных компонентов библиотеки.), стандартная библиотека C ++ зависит от компонентов, поставляемых программой C ++.Если эти компоненты не соответствуют их требованиям, настоящий международный стандарт не предъявляет требований к реализации.

В частности, эффекты не определены в следующих случаях:

...

  • , если какая-либо замещающая функция, функция-обработчик или операция-деструктор завершаются через исключение, если это специально не разрешено в соответствующем Обязательном поведении: абзац.

Поскольку variant::operator= не имеет специальныхутверждение о бросании деструкторов, когда эти деструкторы действительно выбрасывают, является UB.

...