#include <memory>
#include <algorithm>
using namespace std;
class A {
public:
unique_ptr<int> u;
A(){}
A(const A& other): u(new int(*other.u)){} // If I comment this out, it works.
// A(A&&){} // This does not help.
};
int main() {
A a;
A b = a;
swap(a, b);
}
This code does not work - fails with a wall of template errors saying no matching function for call to 'swap(A&, A&)'
. Why? Deleting the second constructor helps, but I need it in other code. I guessed it could be connected with automatical deleting of some constructors when other are defined, but manually adding move constructor does not help either. How can I fix this?
std::swap()
requires its arguments to be move-constructible and move-assignable .
Given:
struct A {
unique_ptr<int> u;
A();
};
A
is swappable, thanks to the implicitly defined move-constructor and move-assignment operators.
But, given:
struct A {
unique_ptr<int> u;
A();
A(A const&);
};
By declaring a user defined copy constructor, you're inhibiting the implicit definition of A
's move constructor and move assignment operator (and by having a non-assignable-copyable member, you're inhibiting the implicit generation of A
's copy constructor and copy assignment operator).
To make A
swappable again, you need to either user-define both (*):
struct A {
unique_ptr<int> u;
A();
A(A const&);
A(A&&);
A& operator=(A&&);
};
or neither, and just add proper copy-assignment:
struct A {
unique_ptr<int> u;
A();
A(A const&);
A& operator=(A const&);
};
but, this will probably defeat your original intent of avoiding deep copies on swap, so you'll probably end up defining all of them anyway.
(*) noexcept specifications omitted just for brevity ...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.