As per C++11 rules 6 things (default constructor, copy constructor, move constructor, copy assignment, move assignment and destructor ) are generated by default. By second rule, when any custom copy, move or destructor is defined then those default operations are not generated. But in my code that follows that is not the case. But this code fails to compile with an error
call to implicitly deleted copy constructor of 'Uni'
When I write my own copy constructor for Uni everything works fine. (It is commented in the code, given for reference )
Any thoughts much appreciated.
Finally , I am running this on Mac, Xcode with LLVM compiler.
many thanks...
#include <iostream>
class A
{
public:
A(int i) :num{i}
{
std::clog<< "ctor A() num = " << num << "\n";
}
A( A const &aRef)
:num{aRef.num}
{
std::clog << " copy ctor A( A const &aRef) num = " << num << "\n";
}
int value()
{
return num;
}
private:
int num;
};
class Uni
{
public:
Uni(A* aptr) : up{aptr}
{
std::clog << " ctor Uni value = " << up.get()->value() << "\n";
}
/*Uni(Uni const &uRef)
{
std::clog << " copy ctor Uni copying obj pointed by unique_ptr\n";
up.reset(uRef.up.get() ? new A{*uRef.up.get()} : nullptr);
}*/
private:
std::unique_ptr<A> up;
};
int main(int argc, const char * argv[])
{
Uni one{new A{10}};
Uni two{one}; //default copy ctor is implicitly deleted. why ?
}
C++11 rules for automatic generation of special members aren't as simple as you posted them. The most important distinction is that in some cases, the member is implicitly declared, but defined as deleted. That's what happens in your case.
C++11, [class.copy]§11:
(Emphasis mine)
More generally, the rules for auto-generated class members are:
If the class has no user-provided constructors, a default constructor is declared.
If the class doesn't have a user-provided copy constructor, one is declared.
If the class has none of { user-provided copy or move constructor, user-provided copy or move assignment operator, user-provided destructor }, a move constructor will be declared (but see (*) below).
If the class doesn't have a user-provided copy assignment operator, one is declared.
If the class has none of { user-provided copy or move constructor, user-provided copy or move assignment operator, user-provided destructor }, a move assignment operator will be declared (but see (*) below).
If the class doesn't have a user-provided destructor, one is declared.
Any automatically declared member can be defined as defaulted (doing the default stuff) or defined as deleted (if you try to use it, you get an error). The rule of thumb is "If the defaulted version makes sense, it will be defined as defaulted. Otherwise, it will be defined as deleted."
In this context, "makes sense" means "doesn't try to call a deleted, ambiguous, inaccessible or otherwise illegal function." For example, the standard bit I quoted in the first part of this answer lists what doesn't "make sense" for copy constructors.
Additionally, an automatically declared copy constructor or copy assignment operator is defined as deleted if the class has a user-provided move constructor or move assignment operator.
(*) If an automatically declared move constructor or move assignment operator would be defined as deleted, it is instead not declared at all. This rule exists so that trying to move such a class implicitly falls back to copying it instead of generating an error.