Программа с конструктором "noexcept", принятым gcc, отклонена clang

код:

struct T { T() {} };

struct S
{
    T t;

    S() noexcept = default;
};

int main()
{
//    S s;
}

g++ 4.9.2 принимает это без ошибок или предупреждений, однако отчет clang 3.6 и 3.7 для строки 7:

error: exception specification of explicitly defaulted default constructor does not match the calculated one

однако, если строка S s; не комментируется, g++ 4.9.2 теперь сообщает:

noex.cc: In function 'int main()':
noex.cc:12:7: error: use of deleted function 'S::S()'
     S s;
       ^
noex.cc:7:5: note: 'S::S() noexcept' is implicitly deleted because its  exception-specification does not match the implicit exception-specification ''
     S() noexcept = default;
     ^

какой компилятор подходит для исходного кода?


Справочная информация:

g++ даже позволяет добавить в main:

std::cout << std::is_constructible<S>::value << 'n';

что выходы 0. Я столкнулся с этой проблемой при использовании clang для компиляции некоторого сложного кода, который сильно использовал шаблоны, SFINAE и noexcept. В этом коде S и T являются классами шаблонов; поэтому поведение зависит от того, какие типы S был создан экземпляр С. Clang отклоняет его с этой ошибкой для некоторых типов, тогда как g++ разрешает его, и SFINAE работает на основе is_constructible и подобные черты.

1 ответов


зависит от версии стандарта, с которым Вы консультируетесь.

N3337 [dcl.fct.защита.по умолчанию] / p2:

явно-дефолтная функция [...] может иметь явное исключение-спецификация только если он совместим (15.4) с исключение-спецификация о неявном заявлении.

Что делает ваш исходный код плохо сформированные.

Это было изменено на проблема CWG 1778 читать (N4296 [dcl.fct.защита.по умолчанию]/Р3):

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

  • если функция явно по умолчанию при первом объявлении, она определяется как удаленная;
  • в противном случае, программа плохо сформированные.

Что означает, что конструктор теперь просто определен как удаленный. (В приведенную выше формулировку включены изменения, внесенные N4285, документ после C++14, вносящий некоторые изменения очистки, предназначенные для чисто редакционного характера. Версия N3936 по существу такая же.)

предположительно GCC реализует разрешение CWG1778, а Clang-нет.