Какова спецификация исключения для дефолтного виртуального деструктора в C++11?

Предположим, у меня есть:

class Foo
{
public:
   virtual ~Foo()=default;
};

Что такое спецификация исключения для дефолтного деструктора? Является ли дефолтный деструктор эквивалентным:

   virtual ~Foo() {};
or
   virtual ~Foo() throw() {};
or
   virtual ~Foo() noexcept {};

Раздел 15.4 стандарта C++11 говорит, что это зависит от спецификаций исключений функций, непосредственно вызываемых неявным определением деструктора. В этом случае нет ни членов, ни базовых классов, поэтому в AFAIK нет функций, напрямую вызываемых неявным деструктором. Это двусмысленность (или упущение) в стандарте?

Это имеет значение, конечно, потому что, если он неявно имеет throw(), тогда все подклассы должны объявить свои деструкторы с помощью throw(). Не говорите мне, что создавать деструкторы - это плохая идея, я это знаю. Я имею дело с большим количеством устаревшего кода, где спецификации исключений не использовались вообще.

В качестве информации, когда я пытался:

class SubFoo : public Foo
{
public:
   virtual ~SubFoo();
};

Я получил ошибку (несоответствующие спецификации исключений) в GCC 4.4 (хотя я признаю, что у меня, возможно, не было правильных ключей командной строки), но не в XCode 4.3 с использованием компиляторов "11".

2 ответа

Вернитесь к предыдущему в том же предложении (§15.4 / 14):

... его неявная спецификация исключений определяет идентификатор типа T в том и только в том случае, если T разрешен спецификацией исключений функции, непосредственно вызванной неявным определением f;... "

Следовательно, если ~Foo не вызывает никаких функций, у него есть неявное объявление, которое не позволяет создавать исключения.

Согласно §15.4/3:

Две спецификации исключений совместимы, если:

  • оба не являются бросающими (см. ниже), независимо от их формы,

Это тот случай, поэтому не имеет значения, является ли объявление throw() или же noexcept - оба совместимы в любом случае.

Стандарт хорошо начинается в C++ 11 §8.4.2 / 2,

Если функция явно по умолчанию в своем первом объявлении,
- неявно считается constexpr, если неявное объявление будет,
- неявно считается, что он имеет ту же спецификацию исключений, как если бы она была неявно объявлена ​​(15.4), …

Но затем, в C++ 11 §15.4 / 14, логика быстро переходит

Неявно объявленная специальная функция-член (раздел 12) должна иметь спецификацию исключения. Если f является неявно объявленным конструктором по умолчанию, конструктором копирования, конструктором перемещения, деструктором, оператором назначения копирования или оператором назначения перемещения, его неявная спецификация исключения определяет идентификатор типа T если и только если T допускается спецификацией исключений для функции, непосредственно вызываемой fнеявное определение; f должен разрешать все исключения, если любая функция, которую он непосредственно вызывает, разрешает все исключения, и f не должно допускать никаких исключений, если каждая функция, которую она непосредственно вызывает, не допускает никаких исключений.

В значении стандарта "разрешить" речь идет о явном разрешении через спецификацию исключений.

Если f вызывает две функции, одна из которых определяет и, следовательно, позволяет Tи один из которых допускает все исключения, то f должны оба указать T и разрешить все исключения, что невозможно.

Так что это определенно выглядит как дефект в стандарте.

Я нашел соответствующий отчет о дефектах, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html.

Тем не менее, похоже, что эта область просто большой беспорядок.:-(

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