[cfe-dev] Move constructor forces copy assignment to be implicitly defaulted?

Steve Ramsey clang at lucena.com
Tue May 29 10:45:24 PDT 2012


On May 28, 2012, at 6:21 PM, Howard Hinnant wrote:
> #include <type_traits>
> #include <string>
> 
> struct A
> {
>   std::string s;
> };
> 
> static_assert(std::is_nothrow_move_constructible<A>::value,
>             "A should be nothorw move constructible");
> 
> struct B
> : public A
> {
>   ~B();
> };
> 
> static_assert(std::is_nothrow_move_constructible<B>::value,
>             "B should be nothorw move constructible");
> 
> A makeA() {
> A a;
> return a;
> }
> 
> B makeB() {
> B b;
> return b;
> }
> 
> int main() {
> A a = makeA();
> B b = makeB();
> }
> 
> test.cpp:18:1: error: static_assert failed "B should be nothorw move constructible"
> static_assert(std::is_nothrow_move_constructible<B>::value,
> ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 1 error generated.
> 
> Since the move constructor in B has been suppressed, it is no longer nothrow to move B.  Now if you add:
> 
>   B() = default;
>   B(B&&) = default;
> 
> 
> then everything will compile.

This is an interesting example, but it muddies things a bit. The std::string member in A is not nothrow-copy-constructible, which is why B is initially not nothrow-move-constructible (though it is still move-constructible, as std::string is copy-constructible); this all follows from the Note in 12.8 p9. Once that is clear, the point of the example comes through; namely, that the move constructor that had been undeclared as per 12.8 p9 can be explicitly declared and defined as defaulted, and the default definition will be nothrow-move-constructible all the way down.

			Steve





More information about the cfe-dev mailing list