模板构造器优先于正常复制和移动构造函数?

And*_*zos 5 c++ c++11

以下程序的输出......

#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)

为什么具体的复制构造函数不优先于模板构造函数?

反正有没有解决它,以便复制和移动构造函数重载将优先于模板构造函数?

Naw*_*waz 5

好吧,这是因为参考崩溃.

在重载解析阶段,当函数模板被实例化时,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)

预计再次产出.


cme*_*erw 2

选择构造函数时,正常的重载解析规则仍然适用 - 并且采用非 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)