G++ - 4.8.1 считает, что явно объявленный деструктор без спецификации исключения всегда не является исключением (true) - программирование
Подтвердить что ты не робот

G++ - 4.8.1 считает, что явно объявленный деструктор без спецификации исключения всегда не является исключением (true)

Рассмотрим следующую программу:

#include <type_traits>

struct Thrower
{
    ~Thrower() noexcept(false) { throw 1; }
};

struct Implicit
{
    Thrower t;
};
static_assert(!std::is_nothrow_destructible<Implicit>::value, "Implicit");

struct Explicit
{
    ~Explicit() {}

    Thrower t;
};
static_assert(!std::is_nothrow_destructible<Explicit>::value, "Explicit");

С g++-4.8.1 на Explicit есть статический отказ утверждения - кажется, что ~Explicit() - noexcept. Это не соответствует моим ожиданиям. Согласно §12.4.3:

Объявление деструктора, не имеющего спецификации исключения, неявно считается, что имеет ту же спецификацию исключения, что и неявное объявление

Самое смешное здесь - проверка Implicit, похоже, ведет себя согласно моей интерпретации § 15.4.14 (через §12.4.7).

... Если f является... destructor... он подразумевает спецификацию исключительных спецификаций... f имеет спецификацию исключения noexcept(true), если каждая функция, которую он вызывает непосредственно, не позволяет исключений.

g++-4.7 отсутствует is_nothrow_destructable, я написал свой собственный, чтобы проверить поведение в 4.7. Кажется, что программа отлично компилируется. Я оставляю за это право быть совершенно неправильным и источником моей путаницы:

template <typename T>
struct is_nothrow_destructible
{
    static constexpr bool value = noexcept(std::declval<T>().~T());
};

TL; DR: Почему g++-4.8.1 считает, что явно объявленный деструктор без спецификации исключения всегда noexcept(true)?


Обновить. Я открыл ошибку: 57645. Если вам действительно нужно обойти эту проблему, вы можете добавить спецификацию исключения для деструктора (например, Thrower в этом примере).

4b9b3361

Ответ 1

TL; DR: Почему g++ - 4.8.1 считает, что явно объявленный деструктор без спецификации исключения всегда noexcept(true)?

Потому что у него есть ошибка?

Ваша интерпретация стандарта верна, и Клэнг реализует ее правильно (утверждение не срабатывает).

f имеет спецификацию исключения noexcept(true), если каждая функция, которую он непосредственно вызывает, не допускает исключений.

Деструктор непосредственно вызывает деструктор всех подобъектов:

§12.4 [class.dtor] p8:

После выполнения тела деструктора и уничтожения любых автоматических объектов, выделенных в теле, деструктор для класса X вызывает деструкторы для прямых невариантных нестатических элементов данных Xs, [...].