TL;DR: see compilers disagree on code by Godbolt link: https://godbolt.org/z/f7G6PTEsh
Should std::variant
be nothrow destructible when its alternative has potentially throwing destructor? Clang and GCC seem to disagree on it (probably different standard library implementations on Godbolt?), MSVC thinks it should. cppreference says variant's destructor does not have noexcept specifications, and in that case destructor should be unconditionally noexcept unless it has potentially throwing members or bases (https://en.cppreference.com/w/cpp/language/noexcept_spec), which is not specified for variant (duh!).
The reason I'm asking is not to mess with throwing stuff out of destructors, but to gradually refactor weird legacy stuff that is minimized to the following snippet ("exception specification of overriding function is more lax than the base version"), and also related bug on dated compiler that we can't update yet.
#include <type_traits>
#include <variant>
struct S
{
~S() noexcept(false);
};
static_assert(std::is_nothrow_destructible_v<std::variant<S>>); // assertion failed with clang
struct Y
{
virtual ~Y() {}
};
struct Z: public Y
{
virtual ~Z() {}
// clang error because of this member:
// exception specification of overriding function is more lax than the base version
std::variant<int, S> member;
}
u.~T()
All resources owned by u are reclaimed, no exceptions are thrown. ..." So an alternative type that can throw on destruction breaks the pre-conditions. – Biologicalnoexcept(false)
, it may still never actually throw, and then it is a valid alternative type for a variant. – Discipline