1

This compiles and calls the copy constructor:

struct foo {
    foo() = default;
    foo(const foo&) { cout << "copy ctor!" << endl; }
    //foo(const foo&&) = delete;
};

int main() {
    foo a;
    foo b(move(a));

This does not compile:

struct foo {
    foo() = default;
    foo(const foo&) { cout << "copy ctor!" << endl; }
    foo(const foo&&) = delete;
};

int main() {
    foo a;
    foo b(move(a));

I know in the first case why the copy is called - the move ctor is not generated. But why doesn't the second snipper compile? It thought it would call the copy ctor again.

here is a link to an online compiler

onqtam
  • 4,356
  • 2
  • 28
  • 50

1 Answers1

1

The difference boils down to absence of move constructor versus deleted move constructor. Those two are not equivalent.


In the first case, the presence of your copy constructor prevents the generation of an implicit move constructor. Hence overload resolution on foo(foo&&) would find one single viable candidate:

foo(const foo& );

That candidate is then selected by default.

In the second case, you do have a move constructor. Overload resolution would find two viable candidates:

foo(const foo& ); // as before
foo(foo&& );      // now this one also exists

The move constructor is the better match, so it's picked as the best viable candidate. However, since it's explicitly defined as deleted, selection of it is ill-formed. Hence the compile error.

Barry
  • 286,269
  • 29
  • 621
  • 977