Declaration of the implicitly declared copy constructor is not, in fact, being suppressed. It's just not being called due to the rules of overload resolution.
The implicitly declared copy constructor has the form Foo(const Foo&)
. The important part of this is that it takes a const reference. Your constructor template takes a non-const reference.
a
is not const, so the non-const user-declared constructor template is preferred over the implicitly-declared copy constructor. To call the implicitly-declared copy constructor, you can make a
const:
const Foo a;
Foo b(a);
or you can use static_cast
to obtain a const reference to a
:
Foo a;
Foo b(static_cast<const Foo&>(a));
The overload resolution rules that describe this are found mostly in §13.3.3.2/3 of the C++0x FCD. This particular scenario, with a combination of lvalue and rvalue references, is sort of described by the various examples on page 303.
A variadic constructor template will suppress the implicitly declared default constructor because a variadic constructor template is user-declared and the implicitly declared default constructor is only provided if there are no user-declared constructors (C++0x FCD §12.1/5):
If there is no user-declared constructor for class X
, a constructor having no parameters is implicitly declared as defaulted.
A variadic constructor template will not suppress the implicitly declared copy constructor because only a non-template constructor can be a copy constructor (C++0x FCD §12.8/2, 3, and 8):
A non-template constructor for class X
is a copy constructor if its first parameter is of type X&
, const X&
, volatile X&
or const volatile X&
, and either there are no other parameters or else all other parameters have default arguments.
A non-template constructor for class X
is a move constructor if its first parameter is of type X&&
, const X&&
, volatile X&&
, or const volatile X&&
, and either there are no other parameters or else all other parameters have default arguments.
If the class definition does not explicitly declare a copy constructor and there is no user-declared move constructor, a copy constructor is implicitly declared as defaulted.