Consider the following example:
#include <iostream>
struct X
{
X() = default;
X(const X&) = default;
X(X&&) = default;
X& operator = (const X&) = default;
X& operator = (X&&) = default;
};
int main()
{
static_assert(std::is_nothrow_move_assignable_v<X>);
return 0;
}
The move assignment operator appears to be implicitly noexcept
, since the static assertion passes.
However, defining it out-of-line makes the assertion fail:
#include <iostream>
struct X
{
X() = default;
X(const X&) = default;
X(X&&) = default;
X& operator = (const X&) = default;
X& operator = (X&&); //= default;
};
X& X::operator=(X&&) = default;
int main()
{
static_assert(std::is_nothrow_move_assignable_v<X>);
return 0;
}
Why do they behave differently?
X& operator = (X&&);
is notnoexcept
. The fact you later use=default
to simplify implementation does not matter. Definition cannot change declaration. – Sclar