在返回从函数的返回类型派生的类型的本地对象时,为什么未选择move构造函数?

在返回从函数的返回类型派生的类型的本地对象时,为什么未选择move构造函数?

问题描述:

Clang 引起以下错误:

prog.cc: In function 'Base foo()': prog.cc:21:12: error: use of deleted function 'Base::Base(const Base&)'
     return d;
            ^

根据[class.copy]/32:

According to [class.copy]/32:

当满足复制/移动操作省略的条件,但不满足异常声明的条件,并且要复制的对象由左值指定,或者当return语句中的表达式为(可能带有括号)id-expression,该对象使用自动存储持续时间命名的对象,该对象在最内层的封闭函数或lambda-expression的主体或参数声明子句中声明,重载分辨率以选择对象的构造函数首先执行复制,就好像该对象是由右值指定的一样

When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue, or when the expression in a return statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue

如果上面的句子打算被解析为(copy elision criteria met && lvalue) || (id-expression designating an automatic object),则表示为此CWG缺陷似乎表明,为什么最后一个条件不适用? Clang和GCC中都存在编译器错误吗?

If the sentence above is meant to be parsed as (copy elision criteria met && lvalue) || (id-expression designating an automatic object), as this CWG defect seems to indicate, why isn't the last condition applying here? Is there a compiler bug both in Clang and GCC?

另一方面,如果该句子应被解析为(copy elision criteria met && (lvalue || id-expression designating an automatic object)),那么这是否值得DR的误导性措辞?

On the other hand, if the sentence is meant to be parsed as (copy elision criteria met && (lvalue || id-expression designating an automatic object)), isn't this a very misleading wording worth a DR?

[class.copy]/32继续:

[class.copy]/32 continues:

[...]如果所选构造函数的第一个参数的类型 不是对对象类型的右值引用(可能是 cv合格),考虑到 对象作为左值.

[...] if the type of the first parameter of the selected constructor is not an rvalue reference to the object's type (possibly cv-qualified), overload resolution is performed again, considering the object as an lvalue.

第一个重载分辨率(将d视为右值)选择Base::Base(Base&&).但是,所选构造函数的第一个参数的类型不是Derived&&而是Base&&,因此将丢弃该重载解析的结果,并再次执行重载解析,将d视为左值.第二个重载解决方案将选择已删除的副本构造函数.

The first overload resolution, treating d as an rvalue, selects Base::Base(Base&&). The type of the first parameter of the selected constructor is, however, not Derived&& but Base&&, so the result of that overload resolution is discarded and you perform overload resolution again, treating d as an lvalue. That second overload resolution selects the deleted copy constructor.