Why destructors of the std type of a smart pointer do not inherit the noexcept dtor status of an object with an object pointer

In C ++ 11, I understand that by default, destructors are implicitly noexcept(true) , except that:

If I have a class C whose destructor is explicitly labeled noexcept(false) (presumably because it throws for some odd reason, and I know you shouldn't and why), then the destructor of any class that comes from C or contains an element of type C , it also becomes noexcept(false) .

However, the class containing std::shared_ptr<C> does not seem to automatically disable its destructor to noexcept(false) , and the same is true to contain std::weak_ptr<C> , std::unique_ptr<C> etc.

Here is a complete example:

 #include <type_traits> #include <memory> struct Normal { ~Normal() { } }; struct ThrowsInDtor { ~ThrowsInDtor() noexcept(false) { throw 42; } }; template<typename T> struct Wrapper { T t; }; template<typename T> struct UniquePtrWrapper { std::unique_ptr<T> t; }; template<typename T> struct SharedPtrWrapper { std::shared_ptr<T> t; }; static_assert(std::is_nothrow_destructible<Normal>::value, "A"); // OK static_assert(!std::is_nothrow_destructible<ThrowsInDtor>::value, "B"); // OK static_assert(std::is_nothrow_destructible<Wrapper<Normal>>::value, "C"); // OK static_assert(!std::is_nothrow_destructible<Wrapper<ThrowsInDtor>>::value, "D"); // OK static_assert(std::is_nothrow_destructible<UniquePtrWrapper<Normal>>::value, "E"); // OK static_assert(!std::is_nothrow_destructible<UniquePtrWrapper<ThrowsInDtor>>::value, "F"); // FAILS static_assert(std::is_nothrow_destructible<SharedPtrWrapper<Normal>>::value, "G"); // OK static_assert(!std::is_nothrow_destructible<SharedPtrWrapper<ThrowsInDtor>>::value, "H"); // FAILS 

It seems strange to me that F and H fail. I expected that the noexcept destructor status of the owned / reference type would extend to the smart pointer destructor, presumably through a noexcept expression such as noexcept(std::is_nothrow_destructible<T>::value) in the smart pointer destructor declaration.

However, the standard does not mention this, and the standard library code I was looking at does not.

Does anyone know why standard smart pointers do not propagate the noexcept instance type destructor status to the smart pointer destructor?

+6
source share
1 answer

std::shared_ptr<T> intended for use with an incomplete T , so there is no way to get the information that you request when declaring your destructor. Alternatively, you can do this:

 std::shared_ptr<void> dummy = std::make_shared<T>(); // for some complete T 

Now what should noexcept say for std::shared_ptr<void> ? This is runtime information from std::shared_ptr POV.

For std::unique_ptr exists

20.7.1.2.2 unique_ptr destructor [unique.ptr.single.dtor]

1 ~unique_ptr();

Required: the expression get_deleter()(get()) must be well-formed, must have well-defined behavior and should not throw exceptions. [Note: to use default_delete it takes T be a full type. -endnote]

This means that the debugger must make sure that it does not throw - which does not necessarily depend on the destructor T , that is, when using zero deletion.

+6
source

Source: https://habr.com/ru/post/956507/


All Articles