Почему деструкторы интеллектуальных указателей типа std не наследуют статус noexcept dtor указанного объекта

В C++11 я понимаю, что по умолчанию деструкторы неявно noexcept(true), Кроме этого:

Если у меня есть класс C который имеет деструктор, явно помеченный noexcept(false) (предположительно потому, что он выбрасывает по какой-то странной причине, и я знаю, что вы не должны и почему), затем деструктор любого класса, который происходит от C или содержит член типа C также становится noexcept(false),

Тем не менее, класс, который содержит std::shared_ptr<C> по-видимому, автоматически его деструктор не переключается на noexcept(false)и то же самое верно для содержания std::weak_ptr<C>, std::unique_ptr<C>, так далее.

Вот полный пример:

#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

Мне кажется странным, что F и H терпят неудачу. Я ожидал, что статус "noexcept" деструктора типа "владелец / ссылка" будет распространяться на деструктор "умный указатель", предположительно, с помощью выражения noexcept, такого как noexcept(std::is_nothrow_destructible<T>::value) на декларации деструктора умного указателя.

Однако в стандарте об этом ничего не говорится, а код стандартной библиотеки, на который я смотрел, этого не делает.

Кто-нибудь знает, почему стандартные умные указатели не передают деструктор умного указателя не исключая статус деструктора инстанцирующего типа?

1 ответ

Решение

std::shared_ptr<T> предназначен для использования с неполным Tследовательно, нет способа получить информацию, которую вы запрашиваете при объявлении деструктора. Также вы можете сделать это:

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

Теперь, что должно noexcept скажем для std::shared_ptr<void>? Это информация времени выполнения от std::shared_ptrPOV.

За std::unique_ptr, есть

20.7.1.2.2 деструктор unique_ptr [unique.ptr.single.dtor]

1 ~unique_ptr();

Требуется: выражение get_deleter()(get()) должен быть правильно сформирован, иметь четко определенное поведение и не создавать исключений. [ Примечание: использование default_delete требует T быть полным типом. - примечание]

Это означает, что удалитель должен убедиться, что он не выбрасывает, что не обязательно зависит от деструктора Tпри использовании null-delete.

Другие вопросы по тегам