I need to check that a destructor of a given type is noexcept
.
I found std::is_nothrow_destructible_v
, but it does not work, as it is true
for destructors that do not have noexcept
. I see that libstdc++
source is complicated and doing something else, so maybe it’s a wrong type trait.
So I am trying to write my own is_noexcept_destructible
, but it does not work either. In addition, the same technique with std::declval
works for a member function, but not for a destructor. What am I doing wrong?
Here is an example code with questions in comments:
#include <iostream>
#include <type_traits> // is_nothrow_destructible_v
template <typename T>
static constexpr auto is_noexcept_destructible = noexcept(std::declval<T&&>().~T());
class Baddy
{
int i;
public:
Baddy();
~Baddy(); // may throw!
void fn(); // may throw!
};
static_assert(is_noexcept_destructible<Baddy>); // why true?
static_assert(std::is_nothrow_destructible_v<Baddy>); // why true?
static_assert(not noexcept(Baddy().~Baddy())); // why universally false?
static_assert(not noexcept(Baddy().fn())); // why universally false?
static_assert(noexcept(std::declval<Baddy&&>().~Baddy())); // why true?
static_assert(not noexcept(std::declval<Baddy&&>().fn())); // OK!
class Gooddy
{
int i;
public:
Gooddy() {}
~Gooddy() noexcept {}
void fn() noexcept {}
};
static_assert(is_noexcept_destructible<Gooddy>);
static_assert(std::is_nothrow_destructible_v<Gooddy>);
static_assert(not noexcept(Gooddy().~Gooddy())); // why false?
static_assert(not noexcept(Gooddy().fn())); // why false?
static_assert(noexcept(std::declval<Gooddy&&>().~Gooddy()));
static_assert(noexcept(std::declval<Gooddy&&>().fn())); // OK!
void bad_fn();
Baddy::Baddy(): i{7} {}
Baddy::~Baddy(){ bad_fn(); }
void Baddy::fn() { bad_fn(); }
void bad_fn() { throw std::logic_error{"misbehave"}; }
int main()
{
auto bad = Baddy{};
bad.fn(); // crash
std::cout << "PASSEDn";
}
Live code: https://godbolt.org/z/j3q7nsGrM