Progtwig con constructor “noexcept” aceptado por gcc, rechazado por clang

El código:

struct T { T() {} }; struct S { T t; S() noexcept = default; }; int main() { // S s; } 

g ++ 4.9.2 acepta esto sin errores ni advertencias, sin embargo, el clang 3.6 y 3.7 reportan para la línea 7:

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

Sin embargo, si la línea S s; no está comentado, g ++ 4.9.2 ahora informa:

 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; ^ 

¿Qué comstackdor es el correcto para el código original?


Fondo:

g ++ incluso permite que se agregue lo siguiente a main :

 std::cout << std::is_constructible::value << '\n'; 

que da salida a 0 . Encontré este problema al usar el Clang para comstackr un código complicado que hizo un uso intensivo de las plantillas, SFINAE y noexcept. En ese código S y T son clases de plantilla; así que el comportamiento depende de con qué tipos S se creó una instancia. Clang lo rechaza con este error para algunos tipos, mientras que g ++ lo permite y SFINAE funciona basándose en rasgos is_constructible y similares.

Depende de la versión del estándar que esté consultando.

N3337 [dcl.fct.def.default] / p2:

Una función explícitamente predeterminada […] puede tener una especificación de excepción explícita solo si es compatible (15.4) con la especificación de excepción en la statement implícita.

lo que hace que su código original mal formado.

Esto fue modificado por el número 1778 de CWG para que se lea (N4296 [dcl.fct.def.default] / p3):

Si una función que está predeterminada por defecto se declara con una especificación de excepción que no es compatible (15.4) con la especificación de excepción en la statement implícita, entonces

  • si la función está predeterminada por defecto en su primera statement, se define como eliminada;
  • De lo contrario, el progtwig está mal formado.

lo que significa que el constructor ahora se define simplemente como eliminado. (La redacción anterior incorporó los cambios realizados por N4285 , un documento posterior a C ++ 14 que realiza algunos cambios de limpieza que pretenden ser puramente editoriales. La versión N3936 es sustancialmente la misma).

Presumiblemente, GCC implementa la resolución de CWG1778, mientras que Clang no lo hace.