以下程序的输出......
#include <iostream>
using namespace std;
struct X
{
X(const X&) { cout << "copy" << endl; }
X(X&&) { cout << "move" << endl; }
template<class T> X(T&&) { cout << "tmpl" << endl; }
};
int main()
{
X x1 = 42;
X x2(x1);
}
Run Code Online (Sandbox Code Playgroud)
是
tmpl
tmpl
Run Code Online (Sandbox Code Playgroud)
所需的输出是:
tmpl
copy
Run Code Online (Sandbox Code Playgroud)
为什么具体的复制构造函数不优先于模板构造函数?
反正有没有解决它,以便复制和移动构造函数重载将优先于模板构造函数?
好吧,这是因为参考崩溃.
在重载解析阶段,当函数模板被实例化时,T被推导为X&,因此T&&(由X& &&)X&引用 - 折叠,并且函数模板中的实例化函数变得完全匹配,并且复制构造函数需要从X&到const X&(这就是为什么没有选择劣质匹配).
但是,如果const从复制构造函数中删除,则首选复制构造函数.试试这个:
X(/*const*/ X&) { cout << "copy" << endl; }
Run Code Online (Sandbox Code Playgroud)
按预期输出.
或者,如果你在函数模板中创建参数,const T&那么将调用copy-constructor(即使它保持不变!),因为reference-collapsing现在不会出现:
template<class T> X(const T &) { cout << "tmpl" << endl; }
Run Code Online (Sandbox Code Playgroud)
预计再次产出.
选择构造函数时,正常的重载解析规则仍然适用 - 并且采用非 const 左值引用的构造函数(对于参数推导后的模板构造函数)比采用 const 左值引用的构造函数更匹配。
当然,您可以添加另一个采用非常量左值引用的重载,即
X(X&) { cout << "copy" << endl; }
Run Code Online (Sandbox Code Playgroud)
更新:模板构造函数更匹配的其他情况:
const X f()
{ return X(); }
struct Y : X
{ Y() { } };
int main()
{
X x3(f()); // const-qualified rvalue
Y y;
X x4(y); // derived class
}
Run Code Online (Sandbox Code Playgroud)