使用模板移动运算符

ano*_*ous 3 c++ templates move-semantics c++11

我有一个模板化的课程,我想避免复制(因为这样做的潜在成本).我可以实现一个移动构造函数,但我还想允许移动"accross template parameter".这是我正在尝试编译的内容:

template <class T>
class Foo
{
public:
    Foo() {}
    template <class U> Foo(Foo<U>&&) {}

private:
    Foo(const Foo&);
};

Foo<int> f() { Foo<float> y; return move(y); }
Foo<int> g() { Foo<int> x; return x; }
Foo<int> h() { Foo<float> z; return z; }
Run Code Online (Sandbox Code Playgroud)

我理解为什么在技术上f编译:move(y)的类型是Foo(float)&&并且碰巧有一个方便的构造函数接受Foo(U)&&,因此编译器设法找到U = float工作.

h不编译.z的类型为Foo(float),我猜这距离Foo(U)&&太远,以确定如果选择U = float,则可以调用移动构造函数...

我不确定为什么g编译,但确实如此.x的类型是Foo(int).编译器如何设法使用move运算符(它不能只是从Foo(int)隐式转换为Foo(int)&&,可以吗?)

所以我的问题是:规则是什么?为什么h编译但g不?有什么我可以在Foo中改变以使h编译?

谢谢

Ker*_* SB 6

复制或移动构造函数不能是模板.从12.8(2,3):

如果类的非模板构造X函数的第一个参数是type ,或,并且没有其他参数,或者所有其他参数都有默认参数(8.3.6)X&,则它是一个复制构造函数.[示例:并且是复制构造函数.]const X&volatile X&const volatile X&X::X(const X&)X::X(X&,int=1)

一个非模板类的构造函数X是一个移动构造函数,如果它的第一个参数是类型的X&&,const X&&,volatile X&&,或const volatile X&&,并且或者有没有其他参数,否则所有其他参数默认参数(8.3.6).[示例:Y::Y(Y&&)是一个移动构造函数.]

所以你的例子fg工作因为你正在调用一个普通的构造函数(而不是一个move -constructor).

f工作原因显而易见,因为结果move(y)可以绑定Foo<float>&&.g原因不同:由于类型x与函数的返回类型相同x,因此返回语句中表达式的值匹配Foo<int>&&.这是因为12.8(31,32):

return具有类返回类型的函数中的语句中,当表达式是具有与函数返回类型相同的cv-unqualified类型的非易失性自动对象(函数或catch子句参数除外)的名称,[ ...]

当满足或将满足复制操作的省略标准时,除了源对象是函数参数这一事实,并且要复制的对象由左值指定,重载决策选择复制的构造函数是首先执行,好像对象是由右值指定的.

最后,我们看到,为什么h不工作:表达式的值zreturn声明中不能结合Foo<float>&&,因为它没有明确投(通过std::move),也没有给出第12.8(32)的特许状,因为它的类型是不一样的作为函数的返回类型.(它只能绑定Foo<float>&(几乎肯定是错误的)或Foo<float> const &.)


顺便说一句,移动不管理外部资源的对象(例如基元)是没有意义的.无论如何都必须复制实际的对象数据.