Suppose I have a class A with a move constructor:
class A {
public:
A(A &&other) = default;
}
Suppose I then have a class with an A member:
class B {
A a;
}
The first part of the question: How can I write a constructor that takes an rvalue reference to A and calls A(A &&)?
If I write this:
class B {
A a;
public:
B(A &&a) : a(a) {}
}
I get the following error:
move_constructor_call.cc:9:16: error: call to implicitly-deleted copy constructor of 'A'
B(A &&a) : a(a) {}
^ ~
move_constructor_call.cc:3:5: note: copy constructor is implicitly deleted because 'A' has a user-declared move constructor
A(A &&other) = default;
^
I assume this is because a is considered an lvalue so the move constructor is not called. But I am not sure why it is not called even though a should have type A &&. Is it a requirement of a move constructor that the value constructed from is an rvalue, as it is not here? I had been under the impression an lvalue of an rvalue reference would suffice.
This is the second part of the question: Why does it not call A(A &&) here?
>Solution :
You can change the initializer list to a(std::move(pa)) as shown below.
This is because the expression a inside the parenthesis in your example has the value category of an lvalue expression.
class B {
A a;
public:
//------------vvvvvvvvv----------->explicitly use std::move
B(A &&pa) : a(std::move(pa)) {}
};