删除元组成员的复制构造函数导致错误

Deleted copy constructor of tuple member cause error

这段代码

#include <tuple>

struct Foo
{
    Foo(const int& value):value_(value){}

    //Foo(const Foo&)=delete; // delete copy constructor

    int value_;
};

int main()
{
    std::tuple<Foo> tup(std::move(Foo(1)));
    return 0;
}

工作正常,但如果删除 Foo 复制构造函数,它将失败并出现以下编译错误:使用已删除的函数 Foo::Foo(const Foo&).

但是,既然我明确告诉对象可以移动,为什么 std::tuple 构造函数使用 Foo 复制构造函数而不是它的移动构造函数?如何强制构建 std::tuple 移动 Foo 实例而不是复制它?

But, since I am telling explicitly that the object can be moved,

不,您是在告诉编译器您想要移动对象。这不是一回事。

why the std::tuple constructor uses the Foo copy constructor instead of its moving constructor?

因为删除复制构造函数时隐含的移动构造函数不存在,所以不能使用

How can I enforce the std::tuple to be constructed moving the Foo instance instead of copying it?

要么不删除复制构造函数,要么也定义一个移动构造函数:

struct Foo
{
    Foo(const int& value):value_(value){}

    Foo(const Foo&)=delete; // delete copy constructor

    Foo(Foo&&)=default;

    int value_;
};

N.B。这里的std::move完全没用:

std::tuple<Foo> tup(std::move(Foo(1)));

std::move 所做的只是将其参数转换为右值,但临时 Foo(1) 已经是右值,因此您将右值转换为右值:无用。此外,如果没有 std::move,编译器可以执行 copy elision 并优化实际移动,但是当您使用 std::move 时,它不能这样做,您将代码设为 更慢而不是更快!

最佳代码是最简单的版本:

std::tuple<Foo> tup(Foo(1));

或者更简单:

std::tuple<Foo> tup(1);