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?

Était-ce utile?

La 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.

Autres conseils

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;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top