sintaxis partes objetos declaracion crear constructores como clase asignacion c++ return language-lawyer move-semantics compiler-bug

c++ - partes - ¿Por qué no se elige mover el constructor al devolver un objeto local de tipo derivado del tipo de retorno de la función?



declaracion de constructores en c++ (1)

[class.copy] / 32 continúa:

[...] si el tipo del primer parámetro del constructor seleccionado no es una referencia de rvalue al tipo del objeto (posiblemente cv calificado), la resolución de sobrecarga se realiza nuevamente, considerando el objeto como un lvalue.

La primera resolución de sobrecarga, que trata d como un valor, selecciona Base::Base(Base&&) . Sin embargo, el tipo del primer parámetro del constructor seleccionado no es Derived&& sino Base&& , por lo que el resultado de esa resolución de sobrecarga se descarta y se vuelve a realizar la resolución de sobrecarga, tratando a d como un lvalor. Esa segunda resolución de sobrecarga selecciona el constructor de copia eliminado.

El siguiente código es rechazado tanto por Clang como por GCC (versiones troncales):

#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 }

Causando el siguiente error:

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

Según [class.copy] / 32:

Cuando se cumplen los criterios para la elección de una operación de copia / movimiento, pero no para una declaración de excepción, y el objeto que se va a copiar se designa con un lvalue, o cuando la expresión en una declaración de retorno es una identificación (posiblemente entre paréntesis) La expresión que nombra un objeto con una duración de almacenamiento automático declarada en el cuerpo o la cláusula de declaración de parámetros de la función de cierre más interna o la expresión lambda, la resolución de sobrecarga para seleccionar el constructor para la copia se realiza primero como si el objeto fuera designado por un valor de r

Si la oración anterior debe analizarse como (copy elision criteria met && lvalue) || (id-expression designating an automatic object) (copy elision criteria met && lvalue) || (id-expression designating an automatic object) , como parece indicar este defecto CWG , ¿por qué no se aplica aquí la última condición? ¿Hay un error de compilación tanto en Clang como en GCC?

Por otro lado, si la oración debe analizarse como (copy elision criteria met && (lvalue || id-expression designating an automatic object)) , ¿no es esta una redacción muy engañosa que vale la pena un DR?