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

标签 c++ return language-lawyer move-semantics compiler-bug

以下代码均被 Clang 拒绝和 GCC (主干版本):

#include <memory>

struct Base 
{
    Base() = default; 
    Base(Base const&) = delete;
    Base(Base&&) = default;
};

struct Derived : Base
{
    Derived() = default; 
    Derived(Derived const&) = delete;
    Derived(Derived&&) = default;
};    

auto foo()
    -> Base
{
    Derived d;    
    return d;   // ERROR HERE
}

导致以下错误:

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

根据[class.copy]/32:

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

如果上面的句子被解析为 (复制省略条件满足 && lvalue) || (id-expression 指定一个自动对象),如 this CWG defect似乎表明,为什么最后一个条件在这里不适用? Clang 和 GCC 中是否存在编译器错误?

另一方面,如果句子被解析为(复制省略条件满足&&(左值|| id-expression指定一个自动对象)),这不是很误导性的措辞值得 DR?

最佳答案

[class.copy]/32 继续:

[...] 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 作为左值。第二个重载决议选择已删除的复制构造函数。

关于c++ - 为什么在返回从函数的返回类型派生的类型的本地对象时不选择 move 构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40039379/

相关文章:

c++ - GCC 5 及更高版本中的 AVX2 支持

java - Android 中的颜色

c++ - 为什么 const 在这个模板结构中丢失了?

html - 什么格式化上下文适用于不创建自己的元素?

java - Java 库设计者明确要求 TreeMap 是红/黑树有什么原因吗?

c++ - 初始化依赖于私有(private)模板类型的静态类成员 (C++)

c++ - 安全地取消 boost asio 截止时间计时器

c++ - 从不同的 C 文件导入函数

比较两个未排序 int 数组的代码。 C

python - 返回实例列表没有区别吗?那性能呢?