Sorry for the overly ambiguous title.(due to the lack of my English skill). Please suggest a better title.
Please consider the following code.
struct A {
typedef std::vector<double> State;
// template <class... Args>
// A(Args... args)
// : a(args...)
// {}
template <class... Args>
A(Args&&... args)
: a(std::forward<Args>(args)...)
{}
A(const A&) = default;
A(A&&) = default;
State a;
};
int main(){
A a(3,2);
A b = a; // This line triggers an error!!
}
Gcc 4.8.0 failed to compile it with the error message
error: no matching function for call to 'std::vector<double>::vector(A&)' : a(std::forward<Args>(args)...)
.
I cannot understand why this code is wrong. In my opinion, the compiler should invoke copy constructor in the line A b = a;
.
However if I replace the constructor by the commented one(which simply takes values). It does compile. Furthermore, now the lines for default copy(and move) constructors are not needed. What happens here?
In C++11 having the compiler automatically deduce template parameters (as you must do with a templated constructor) and applying &&
to the type creates a universal reference, which matches any type with any cv qualification, whether it's an lvalue or rvalue reference.
So in your case you're passing in an A
, and therefore Args...
=A &
, Args &&...
=A & &&
, which is A &
thanks to reference-collapsing rules, which is a better match than const A &
, since the compiler doesn't have to add constness to a non-const variable.
I think in this case the template constructor is a better match because it takes non-const value. if you change a
to const
it would call the copy constructor...
const A a(3,2);
A b = a;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With