Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top