The rules in the link Pradhan supplied in the comments can be intuitively understood as follows: the compiler will try to define a copy constructor with argument const T&
if possible; if not then it will try to define a copy constructor with argument T&
; and if that is not possible either, then the copy constructor will be defined as deleted.
When an object of class type T
is copied, its base classes and non-static data members must be copied too. So if one of these, say, U
has a copy constructor that takes U&
instead of const U&
, then it's a no-go if T
's constructor takes const T&
since all subobjects will then be cv-qualified too, and you can't obtain the U&
. Consequently the compiler has to give up on making a copy constructor that takes const T&
, and goes with T&
instead. And similarly, if some base class or non-static data member can't be copied, then it makes sense for the compiler to generate a deleted copy constructor for T
.
For copy assignment operators the rules are basically the same, except the compiler looks for the copy assignment operators of the base classes and non-static data members (rather than their copy constructors), and copy assignment operators are allowed to take their arguments by value (unlike copy constructors).