在返回从函数的返回类型派生的类型的本地对象时,为什么未选择move构造函数?
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.