C++11 - 元组和移动语义

4

这段示例代码是否能够编译通过? clangg++ 可以编译通过,而 icc 14 则会报错,指出在 auto t = ... 这一行中,std::unique_ptr 的复制构造函数未定义。

#include <iostream>
#include <memory>
#include <tuple>

std::tuple<std::unique_ptr<int[]>, int> foo()
{
    std::unique_ptr<int[]> a;
    unsigned int b;
    auto t = std::make_tuple(std::move(a), b); 
    return std::move(t);
}

int main()
{
    foo();
}

返回 rvalues 有什么问题? - akappa
但我返回的是 T,而不是 T&&。我认为这样做应该是安全的。 - akappa
抱歉,没有注意到。 :) - David G
3
不过,你应该删除对返回值调用 std::move 的部分,因为它并不必要,并且会抑制 RVO。 - Benjamin Lindley
好的,谢谢你的提示,尽管那不是我问题的重点。 - akappa
这就是为什么它是一条注释,而不是一个答案。 - Benjamin Lindley
1个回答

6
我认为它应该能够编译:从 std::make_tuple() 得到的结果是一个临时的 std::tuple<T...>,它应该可以移动构造其成员。更准确地说,std::tuple<T...> 的移动构造函数是默认的,应该会导致按成员移动构造。
显然,并没有真正需要将 std::make_tuple() 的结果赋值给 t。如果您选择引入这个变量,则在返回时不应该使用 std::move(t):当 return 语句中的表达式是局部变量时,它会被视为 rvalue。然而,额外的 std::move() 会抑制复制/移动省略。

1
额外的std::move()会阻止复制/移动省略,然而。+1 - ScarletAmaranth
1
因此,英特尔的编译器并不像他们所宣传的那样准备好支持C++11。 - akappa
3
可能是编译器或库的问题。你可能想创建一个测试用例,完全不使用库,而是使用一个包含默认移动构造函数和一个std::unique_ptr<int>的结构体,并查看其行为如何。 - Dietmar Kühl
也许是库的问题。使用这段代码:http://pastebin.com/t39F1iiH,ICC没有抱怨。 - akappa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接