The following code fails for struct X on gcc 4.8.2 with: bla.cpp:15:3: error: function ‘X::X()’ defaulted on its first declaration with an exception-specification that differs from the implicit declaration ‘X::X()’ X() noexcept = default; bla.cpp:16:6: error: function ‘X& X::operator=(X&&)’ defaulted on its first declaration with an exception-specification that differs from the implicit declaration ‘X& X::operator=(X&&)’ X& operator=(X&&) noexcept = default; #include <type_traits> template<bool b> struct F { F() noexcept(b) {} F& operator=(F&&) noexcept(b) {return *this;} }; struct Simple { Simple() noexcept {} Simple& operator=(Simple&&) noexcept {return *this;} }; struct X { X() noexcept = default; X& operator=(X&&) noexcept = default; F<true> f; }; struct X2 { X2() /* noexcept */ = default; X2& operator=(X2&&) /* noexcept */ = default; F<true> f; }; struct X3 { X3() noexcept = default; X3& operator=(X3&&) noexcept = default; Simple f; }; static_assert(std::is_nothrow_constructible<X>::value, ""); static_assert(std::is_nothrow_move_assignable<X>::value, ""); static_assert(std::is_nothrow_constructible<X2>::value, ""); static_assert(std::is_nothrow_move_assignable<X2>::value, ""); static_assert(std::is_nothrow_constructible<X3>::value, ""); static_assert(std::is_nothrow_move_assignable<X3>::value, ""); X2 shows that a noexcept function is implicitly generated. X3 shows that it is necessary for the noexcept operator to depend on a template parameter to trigger this behavior.
Trunk doesn't give the same errors, but fails two of the assertions: n.cc:30:1: error: static assertion failed: static_assert(std::is_nothrow_constructible<X>::value, ""); ^ n.cc:31:1: error: static assertion failed: static_assert(std::is_nothrow_move_assignable<X>::value, ""); ^
(In reply to Jonathan Wakely from comment #1) > Trunk doesn't give the same errors, but fails two of the assertions: > > n.cc:30:1: error: static assertion failed: > static_assert(std::is_nothrow_constructible<X>::value, ""); The reason seems to be that the compiler makes this a deleted function, arguing "'X::X() noexcept' is implicitly deleted because its exception-specification does not match the implicit exception-specification 'noexcept (<uninstantiated>)' X() noexcept = default;" This looks incorrect to me.
This is fixed for 5.0.