unidos tributaria trabaja taxpayeradvocate que para news idverify guia gov estados español dias deducciones c++ c++11 return implicit-conversion move-semantics

c++ - tributaria - que es el irs



¿Cuándo es necesario un movimiento explícito para una declaración de devolución? (1)

Actualizar:

El movimiento explícito no debería ser necesario en las versiones modernas del compilador.

Core DR 1579 cambió las reglas para que el valor de retorno se trate como un valor de r, incluso cuando los tipos no son los mismos. GCC 5 implementa la nueva regla, tanto para C ++ 11 como para C ++ 14.

Respuesta original:

Esto no es una limitación de unique_ptr , es una limitación del idioma, la misma limitación se aplica a cualquier declaración de return que llame a un constructor de conversión que tome una referencia de valor de r:

struct U { }; struct T { T(U&&) { } }; T f() { U u; return u; // error, cannot bind lvalue to U&& }

Esto no se compilará porque [class.copy] / 32 dice:

Cuando los criterios para la elección de una operación de copia se cumplen o se cumplirían, salvo por el hecho de que el objeto de origen es un parámetro de función, y el objeto que se va a copiar se designa mediante un lvalor, la resolución de sobrecarga para seleccionar el constructor para la copia es Primero se realiza como si el objeto fuera designado por un valor de r.

Esto significa que la expresión en una declaración de return solo puede tratarse como un valor de r si es elegible para elision de copia / movimiento (también conocido como NRVO) pero eso es demasiado restrictivo porque significa que solo se aplica cuando el tipo es exactamente el mismo, aunque La variable siempre está fuera de alcance, por lo que sería razonable tratarla siempre como un valor (técnicamente, como un valor x, un valor que expira ).

Esto fue suggested recientemente por Richard Smith (y anteriormente por Xeo) y creo que es una muy buena idea.

En un comentario a otra pregunta, Jonathan Wakely responde a mi declaración:

Nunca necesita un movimiento explícito para un valor de retorno de función de variable local. Es un movimiento implícito allí.

->

... nunca digas nunca ... Necesitas un movimiento explícito si la variable local no es del mismo tipo que el tipo de retorno, por ejemplo, std::unique_ptr<base> f() { auto p = std::make_unique<derived>(); p->foo(); return p; } std::unique_ptr<base> f() { auto p = std::make_unique<derived>(); p->foo(); return p; } std::unique_ptr<base> f() { auto p = std::make_unique<derived>(); p->foo(); return p; } , pero si los tipos son los mismos, se moverá si es posible ...

Así que a veces parece que tenemos que mover una variable local en el retorno.

El ejemplo

std::unique_ptr<base> f() { auto p = std::make_unique<derived>(); p->foo(); return p; }

Es agradable ya que da un error de compilación.

> prog.cpp:10:14: error: cannot convert ‘p’ from type > ‘std::unique_ptr<derived>’ to type ‘std::unique_ptr<derived>&&’

pero me pregunto si hay una buena posibilidad de detectar esto en general, ¿y es aquí un límite de las reglas de idioma o de unique_ptr ?