g++-4.8.1 считает, что явно объявленный деструктор без спецификации исключения всегда noexcept(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 является... деструктором... это неявная спецификация исключений определяет... 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 есть в примере).

1 ответ

Решение

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

Потому что это ошибка?

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

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

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

§12.4 [class.dtor] p8:

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

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