I've already tried to ask this question but I wasn't clear enough. So here is one more try. And I am very sorry for my English ;)
Let's see the code:
#include <iostream>
#include <memory>
using namespace std;
struct A {
unique_ptr<int> ref;
void printRef() {
if (ref.get())
cout<<"i="<<*ref<<endl;
else
cout<<"i=NULL"<<endl;
}
A(const int i) : ref(new int(i)) {
cout<<"Constructor with ";
printRef();
}
~A() {
cout<<"Destructor with";
printRef();
}
};
int main()
{
A a[2] = { 0, 1 };
return 0;
}
It can not be compiled because unique_ptr has deleted copying constructor.
Orly?!
This class DOES HAVE an implied moving constructor because unique_ptr has one.
Let's do a test:
#include <iostream>
#include <memory>
using namespace std;
struct A {
unique_ptr<int> ref;
void printRef() {
if (ref.get())
cout<<"i="<<*ref<<endl;
else
cout<<"i=NULL"<<endl;
}
A(const int i) : ref(new int(i)) {
cout<<"Constructor with ";
printRef();
}
// Let's add a moving constructor.
A(A&& a) : ref(std::move(a.ref)) {
cout<<"Moving constructor with";
printRef();
}
~A() {
cout<<"Destructor with";
printRef();
}
};
int main()
{
A a[2] = { 0, 1 };
return 0;
}
I've added a moving constructor and now the code can be compiled and executed.
Even if the moving constructor is not used.
The output:
Constructor with i=0
Constructor with i=1
Destructor withi=1
Destructor withi=0
Okay...
Let's do one more test and remove the copying constructor (but leave the moving one).
I don't post the code, there only one line has been added:
A(const A& a) = delete;
You should trust me - it works. So the compiler doesn't require a copying constructor.
But it did! (a facepalm should be here)
So what's going on? I see it completely illogical! Or is there some sort of twisted logic I don't see?
Once more:
unique_ptr has a moving constructor and has a deleted copying constructor. Compiler requires copying constructor to be present. But in fact the compiler requires a moving constructor (even if it is not used) and doesn't require a copying (because it could be deleted). And as I see the moving constructor is (should be?) present impliedly.
What's wrong with that?
P.S. One more thing - if I delete the moving constructor the program could not be compiled. So the moving constructor is required, but not the copying one.
Why does it require copy-constructor if it's prohibited to use it there?
P.P.S. Big thanks to juanchopanza's answer! This can be solved by:
A(A&& a) = default;
And also big thanks to Matt McNabb.
As I see it now, the moving constructor is absent because unique_ptr doesn't have a copying one the class has a destructor (and the general rule is that default/copying/moving constructors and destructor could be generated by default only all together). Then the compiler doesn't stop at moving one (why?!) and falls back to copying one. At this point the compiler can't generate it and stops with an error (about the copy constructor) when nothing else can be done.
By the way it you add:
A(A&& a) = delete;
A(const A& a) = default;
It could NOT be compiled with error about 'A::A(A&& a)' deletion, There will be no fall back to copying constructor.
P.P.P.S The last question - why does it stop with error at the COPY constructor but not the MOVE constructor?!
GCC++ 4.7/4.8 says: "error: use of deleted function ‘A::A(const A&)’"
So it stops at copy constructor.
Why?! There should be 'A::A(A&&)'
Ok. Now it seems like a question about move/copy constrcutor choosing rule.
I've created the new more specific question here