son semanticas semantica que nuevas las etiquetas etiqueta estructurales estructura ejemplos cuales c++ c++11

c++ - semanticas - que son las etiquetas en html5



¿La devolución de un objeto local requiere movimiento semántico? (2)

Con respecto a este:

Foo g() { Foo a; return a; } // gcc complains, clang is fine

GCC tiene razón, esto no debería compilar debido a [class.copy]/32 (énfasis mío):

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 return 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 . Si la primera resolución de sobrecarga falla o no se realizó, o si el tipo del primer parámetro del constructor seleccionado no es una referencia de valor al tipo del objeto (posiblemente calificada como CV), la resolución de sobrecarga se realiza nuevamente, considerando el objeto como un lvalue [ Nota: esta resolución de sobrecarga de dos etapas se debe realizar independientemente de si se producirá elision de copia. Determina el constructor que se llamará si no se realiza el elision, y el constructor seleccionado debe ser accesible incluso si la llamada es eluida. "Nota final "

Por lo tanto, la implementación debe elegir mover el constructor para elision y, a medida que se elimina, el programa está mal formado.

Al devolver un objeto local por valor, los compiladores de C ++ pueden optimizar copias innecesarias (elision de copia) aprovechando la semántica de movimiento.
" puede optimizar" implica que si no se cumplen las condiciones adecuadas, el comportamiento debería recurrir al retorno predeterminado por semántica de valor, basado en la copia.
Por lo tanto, como lo entiendo, siempre es válido devolver un objeto copiable por valor.

Pero los compiladores (clang y gcc) no parecen estar de acuerdo con mi interpretación, como lo muestra el MWE a continuación.

class Foo { public: Foo(); Foo(const Foo&); Foo(Foo&&) = delete; } Foo f() { return Foo(); } // error: call to explicitly deleted constructor of ''Foo'' Foo g() { Foo a; return a; } // gcc complains, clang is fine Foo x = g(); // error: call to explicitly deleted constructor of ''A''

P1: ¿La devolución por valor requiere que el objeto sea movible?
P2: Si no es así, ¿gcc y clang se comportan mal en mi MWE o me estoy perdiendo algo más?


Simplemente está cumpliendo con el comportamiento previsto de la resolución de sobrecarga: Foo() es un valor, por lo que la resolución de sobrecarga considera al constructor Foo(Foo&&) como la mejor coincidencia. Desde que se elimina esa sobrecarga, su programa está mal formado. Además, hay una regla especial que dice Foo a; return a; Foo a; return a; También realizará la resolución de sobrecarga como si primero fuera un valor. (La regla se aplica esencialmente siempre que la declaración de devolución sea elegible para elección de copia).

Todo esto está funcionando según lo previsto. Fue usted quien eliminó la sobrecarga, por lo que solicitó expresamente que tales construcciones estén prohibidas.

Tenga en cuenta que el código "real" no suele encontrar este obstáculo, ya que tan pronto como declare un constructor de copia, su clase no tendrá ningún constructor de movimientos. Pero se esforzó por decir "no, en realidad quiero un constructor de movimientos, y quiero que sea un error si alguien intenta usarlo".