The rules governing the exception specification for your two examples are discussed in section 8.4.2 / 2 [dcl.fct.def.default]
... If the function is clearly defaulted in the first declaration,
- it is implicitly considered constexpr if the implied declaration will be,
- it is implicitly considered to have the same exception specification as if it were implicitly declared (15.4) and
โ...
Bar move constructor noexcept(true) , because in ยง15.4 / 14 [except.spec]
An implicitly declared special member function (clause 12) must have an exception specification. If f is an implicitly declared default constructor, copy constructor, constructor move constructor , destructor, copy assignment operator or redirection operator, its implicit exception specification indicates the type -id T if and only if T allowed by the exception specification for the function directly called f implicit definition; f allows all exceptions if any function that it calls directly allows all exceptions, and f does not allow exceptions if every function it calls does not allow exceptions .
The rules in ยง8.4.2 / 2 do not apply to special member functions that were clearly defaulted after the initial declaration, with the exception of destructors which are special in ยง12.4 / 3, which should be noexcept(true) if you do not declare it noexcept(false) or destructors of one of the data elements or base classes may throw.
Thus, if you do not specify Foo(Foo&&) as noexcept(true) , it is assumed that it is noexcept(false) .
The reason why you need to add the noexcept specification of both the declaration and the more explicit default declaration is contained in ยง15.4
3 Two exception specifications are compatible if:
- both of them do not drop (see below), regardless of their shape,
โ...
4 If any function declaration has an exception specification that is not a noexcept specification that allows all exceptions, all declarations, including the definition and any explicit specialization, must have a compatible exception specification ....