移动构造函数模板elision

时间:2014-02-19 05:00:52

标签: c++ c++11

在下面的代码中,移动构造函数调用的原因是什么?

struct Foo {
    Foo() = default;

    Foo(const Foo&) { cout << "Foo(const Foo&)" << endl; }
    template<class T> Foo(T&&) { cout << "Foo<T>(T&&)" << endl; }
};

auto f = Foo{};

输出:Foo<T>(T&&)

检查了铿锵3.3,g ++ 4.9。

添加默认或用户定义的移动构造函数会导致根本没有输出。为什么编译器不会删除调用移动构造函数模板?为什么对非模板的调用被删除,即使它是用户定义的(即编译器如何知道它没有副作用并且可以安全地省略)?

2 个答案:

答案 0 :(得分:4)

要成为移动构造函数并因此成为elision的候选者,构造函数不能是模板实例化(类似地,模板可以生成具有相同签名的构造函数的事实不会阻止生成默认版本。)< / p>

在您的示例中,显式复制构造函数的存在阻止了隐式生成默认移动构造函数,因此构造函数模板已实例化(即使它共享签名也不是移动构造函数)。

如果你添加一个显式(默认或不是)移动构造函数,它将被使用(并且可以 - 但不是必须 - 被省略)。

答案 1 :(得分:0)

原因是因为复制和移动构造函数被定义为非模板(12.8 / 2,12.8 / 3),复制/移动省略规则不适用于此构造函数模板(12.8 / 31)。

添加默认或用户定义的移动构造函数(在本例中)会导致不同的输出(和移动省略),因为用户定义的复制构造函数会阻止编译器隐式生成默认值,因此首先回答错误:

  

12.8 / 7   如果类定义没有显式声明复制构造函数,则会隐式声明一个。如果上课   definition声明了一个move构造函数或move赋值运算符,隐式声明的复制构造函数被定义为deleted;否则,它被定义为默认值(8.4)。