¿Cuál es la razón detrás del comportamiento decltype?


Como entendí en C++11 decltype(expression) se usa para deducir exactamente el mismo tipo de la expresión dada. Pero cuando la expresión se pone entre paréntesis, entonces el tipo deduce es lvalue referencia al tipo de expresión. Por ejemplo:

int x;
decltype(x) y = x;

Es equivalente a int y = x; pero

int x;
decltype((x)) y = x;

Es equivalente a int& y = x;.

Respectivamente

 decltype(auto) f1()
 {
   int x = 0;
   return x; // decltype(x) is int, so f1 returns int
 }

Pero

 decltype(auto) f2()
 {
   int x = 0;
   return (x); // decltype((x)) is int&, so f2 returns int&
 }

¿Cuál es la razón para que este comportamiento sea elegido por el estándar comité?

Palabras posteriores:

Ahora observé que al menos en el caso de GCC 6.2 implementación cuando la expresión en los paréntesis es más compleja por ejemplo decltype((x + x)) el tipo deducido es T, pero no T&. Esto es aún más confuso. No se si este comportamiento es estándar.

Author: bobeff, 2016-10-27

3 answers

Querían una forma de obtener el tipo de declaración de un identificador.

También querían una forma de obtener el tipo de una expresión, incluyendo información sobre si es temporal o no.

decltype(x) indica el tipo declarado del identificador x. Si pasa decltype algo que no es un identificador, determina el tipo, luego agrega & para lvalues, && para xvalues, y nada para prvalues.

Conceptualmente se puede pensar en ella como la diferencia entre la tipo de una variable y el tipo de una expresión. Pero no es así como la norma lo describe.

Podrían haber usado dos palabras clave diferentes para significar estas dos cosas. No lo hicieron.

 35
Author: Yakk - Adam Nevraumont,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-27 21:20:21

Hay cierta necesidad de discriminar entre una entidad y una expresión.

Considere la siguiente pregunta:

¿Cuánto dura Mississippi?

Hay dos respuestas a esta pregunta:

    Mississippi tiene 2.320 millas de largo.
  1. Mississippi tiene 11 letras de largo.

De manera similar, cuando se pregunta sobre el tipo de x, y x es un identificador, no está claro si se refiere al tipo que se usó para declarar que identificador (es decir, el tipo asociado al nombre x), o el tipo de expresión consistente en la sola mención de ese identificador. De hecho, podría haber dos palabras clave diferentes (por ejemplo, entity_type y expr_type) en lugar de una sola sobrecargada decltype. Por alguna razón, el comité optó por sobrecargar decltype para esos dos usos diferentes.

 24
Author: Leon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-27 10:53:12

De uno de los autores de la decltype propuesta, J. Jarvi:

Ha pasado un tiempo, pero esto es lo que (creo que) recuerdo:

Dos palabras clave separadas para diferenciar estos dos tipos de semántica nunca fue considerado. (La introducción de nuevas palabras clave no se hace a la ligera).

En cuanto al cambio de la semántica de decltype((x)), la discusión en el core working group converged to treating (x) as an expression, rather que un identificador, que quizás es más "internamente consistente" con las reglas del idioma.

La gente era consciente de que esto podría ser potencialmente confuso en algunos casos, pero el consenso (aunque quizás no la preferencia de todos) fue finalmente para ser consistente con la definición previa de la norma de qué es un identificador y qué es una expresión.

El ejemplo al que enlazas [el ejemplo de esta pregunta] es realmente sorprendente. En ese momento, deduciendo un tipo de retorno de la función desde su expresión de retorno usando decltype(auto) todavía no era parte del lenguaje, así que no creo que este uso en particular el caso estaba en el radar de cualquiera.

 18
Author: Columbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-27 12:39:00