This actually has nothing to do with the fact that the constructor is variadic. The following class with a non-variadic constructor template exhibits the same behavior:
struct Foo
{
Foo() { }
Foo(const Foo& x)
{
std::cout << "copy constructor
";
}
template <typename T>
Foo(T&& x)
{
std::cout << "template constructor
";
}
};
The problem is that the constructor template is a better match. To call the copy constructor, a qualification conversion is required to bind the non-const lvalue f1
to const Foo&
(the const qualification must be added).
To call the constructor template, no conversions are required: T
can be deduced to Foo&
, which after reference collapsing (Foo& &&
-> Foo&
), gives the parameter x
type Foo&
.
You can work around this by providing a second copy constructor that has a non-const lvalue reference parameter Foo&
.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…