The code:
struct T { T() {} };
struct S
{
T t;
S() noexcept = default;
};
int main()
{
// S s;
}
g++ 4.9.2 accepts this with no errors or warnings, however clang 3.6 and 3.7 report for line 7:
error: exception specification of explicitly defaulted default constructor does not match the calculated one
However, if the line S s;
is not commented out, g++ 4.9.2 now reports:
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;
^
Which compiler is right for the original code?
Background:
g++ even allows the following to be added to main
:
std::cout << std::is_constructible<S>::value << '\n';
which outputs 0
. I encountered this problem when using clang to compile some complicated code that made heavy use of templates, SFINAE and noexcept. In that code S
and T
are template classes; so the behaviour depends on which types S
was instantiated with. Clang rejects it with this error for some types, whereas g++ permits it and the SFINAE works based on is_constructible
and similar traits.
Depends on the version of the standard you are consulting.
N3337 [dcl.fct.def.default]/p2:
An explicitly-defaulted function [...] may have an explicit exception-specification only if it is compatible (15.4) with the exception-specification on the implicit declaration.
which renders your original code ill-formed.
This was changed by CWG issue 1778 to read (N4296 [dcl.fct.def.default]/p3):
If a function that is explicitly defaulted is declared with an exception-specification that is not compatible (15.4) with the exception specification on the implicit declaration, then
- if the function is explicitly defaulted on its first declaration, it is defined as deleted;
- otherwise, the program is ill-formed.
which means that the constructor is now merely defined as deleted. (The above wording incorporated changes made by N4285, a post-C++14 paper making some cleanup changes intended to be purely editorial. The N3936 version is substantively the same.)
Presumably GCC implements CWG1778's resolution, while Clang doesn't.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With