请考虑以下代码:
class SILPassPipelinePlan final {
public:
SILPassPipelinePlan() = default;
~SILPassPipelinePlan() = default;
SILPassPipelinePlan(const SILPassPipelinePlan &) = default;
SILPassPipelinePlan(SILPassPipelinePlan &&) = delete;
SILPassPipelinePlan x() {
SILPassPipelinePlan P;
return P;
}
};
int main() {
return 0;
}
MSVC报告以下错误:
1> consoleapplication2.cpp(13):错误C2280:'SILPassPipelinePlan :: SILPassPipelinePlan(SILPassPipelinePlan&&)':尝试引用已删除的函数
1> consoleapplication2.cpp(8):注意:请参阅'SILPassPipelinePlan :: SILPassPipelinePlan'的声明
Clang和GCC没有。
从规范的角度来看,哪个编译器是正确的?这是一个MSVC错误,还是一个Clang错误?
MSVC来自最新的Visual Studio 2015 Update 3,Clang是版本3.9.0。
答案 0 :(得分:7)
C ++ 11在某些情况下引入了隐式移动 - yours included:
在以下复制初始化上下文中,可能会执行移动操作 用来代替复制操作:
如果return语句([stmt.return])中的表达式是一个(可能带括号的) id-expression ,它将一个对象命名为 在身体或身体中声明的自动存储持续时间 最里面的封闭函数的 parameter-declaration-clause 或 lambda-expression ,或
[...]
重载决策首先选择复制的构造函数 表现为好像该对象是由右值指定的。如果是第一个 重载决议失败,[...]
Clang(唯一接受的实施,顺便说一下。)要么误解,要么失败"包括已删除功能的选择,或过于宽松地应用[over.match.funcs]/8。请参阅错误31025。
答案 1 :(得分:4)
Wandbox上的所有GCC版本都拒绝此代码。您是否有机会在Mac上测试它并使用其Clang-masquerading-as-GCC?
这与P0135无关。 Clang只是在当前[class.copy.elision]/3中对“失败”进行了过于自由的解读,其中表示在这种情况下
重载决策首先选择复制的构造函数 表现为好像该对象是由右值指定的。如果是第一个 重载分辨率失败或未执行,[...],重载 再次执行分辨率,将对象视为左值。
重载决议不会失败;它成功并选择移动构造函数,它恰好被删除。这应该是事情的结束。
此报告为bug 31025。