Reputation: 141638
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.
Upvotes: 24
Views: 8172
Reputation: 137425
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.
Upvotes: 27