https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94644
Daniel Krügler <daniel.kruegler at googlemail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |daniel.kruegler@googlemail. | |com --- Comment #1 from Daniel Krügler <daniel.kruegler at googlemail dot com> --- First: The issue is unrelated to the "nothrow" part of the trait. The whole discussion can be reduced by considering the std::is_move_constructible trait alone, because it is the one that is causing the violations of your expectations. Now, is_move_constructible is just a special case of is_constructible: "For a referenceable type T, the same result as is_constructible_v<T, T&&>, otherwise false." Let's now look at is_constructible (I'm omitting the part of the definition that is unrelated to object types): << The predicate condition for a template specialization is_constructible<T, Args...> shall be satisfied if and only if the following variable definition would be well-formed for some invented variable t: T t(declval<Args>()...); [Note: These tokens are never interpreted as a function declaration. —end note] >> Now consider that your would try to write this variable definition with your type future_state_base (which has a protected destructor): It would be ill-formed, because for the variable definition you need a publicly accessible destructor. Therefore std::is_move_constructible<future_state_base>::value should be false as well as std::is_nothrow_move_constructible<future_state_base>::value. That's the reason why the first static_assert(std::is_nothrow_move_constructible<future_state_base>::value, "future_state_base's move constructor must not throw"); is required to fail (That is when foo is defined), because static_assert(std::is_move_constructible<future_state_base>::value, "future_state_base doesn't meet is_move_constructible"); is required to fail. The actual error in gcc seems to me the behaviour, when foo is not defined and when your second assertion (which is wrong) holds. This looks like a gcc error indeed and I think that clang is just right.