删除的构造函数 - MSVC报告错误,Clang没有

时间:2016-12-22 12:57:28

标签: c++ gcc visual-c++ clang language-lawyer

请考虑以下代码:

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。

2 个答案:

答案 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