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

Howard Hinnant hhinnant at apple.com
Mon May 28 15:21:59 PDT 2012


On May 28, 2012, at 4:26 PM, Suman Kar wrote:

> A quick question:
> 
> struct A {};
> 
> struct B : A { ~B() {} };
> 
> A makeA() {
> A a;
> return a;
> }
> 
> B makeB() {
> B b;
> return b;
> }
> 
> int main() {
> A a = makeA();
> B b = makeB();
> }
> 
> Is it correct to assume that A will be moved and B will not?

Yes.

> Should a
> diagnostic be required for the call to makeB?

No.  B should be allowed to to suppress an implicit move constructor.  The implicit version might do the wrong thing.

But you can create your own compile-time diagnostic.

#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.

Howard




More information about the cfe-dev mailing list