对于过于模糊的标题感到抱歉。(由于缺乏我的英语技能)。请建议一个更好的标题。
请考虑以下代码。
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无法使用错误消息进行编译
error: no matching function for call to 'std::vector<double>::vector(A&)' : a(std::forward<Args>(args)...)
。
我无法理解为什么这段代码错了。在我看来,编译器应该在行A b = a;
中调用复制构造函数。
但是,如果我用注释的构造函数替换构造函数(它只是取值)。它确实编译。此外,现在不需要默认复制(和移动)构造函数的行。 这里发生了什么?
答案 0 :(得分:9)
在C ++ 11中,编译器自动推导出模板参数(正如你必须使用模板化构造函数)并将&&
应用于该类型创建一个通用引用,它匹配任何具有任何cv限定的类型,它是左值或左值参考。
因此,在您的情况下,您传递A
,因此Args...
= A &
,Args &&...
= A & &&
,即{{1}感谢reference-collapsing规则,这是一个比A &
更好的匹配,因为编译器不必将constness添加到非const变量。
答案 1 :(得分:3)
我认为在这种情况下,模板构造函数是一个更好的匹配,因为它采用非const值。如果您将a
更改为const
,则会调用复制构造函数...
const A a(3,2);
A b = a;